Linux has a number of APIs that can be used to set system time: we can use time(), gettimeofday(),clock_gettime() to get the time, and we can usestime(), settimeofday(),clock_settime() to set the time.
However, I noticed that some of these APIs are marked as "deprecated" or "obsolete". I couldn't find the reason behind this deprecation. Specifically:
Why is stime() deprecated (source) but not time()? gettimeofday() offers higher resolution than time(), but the former rather than the latter was declared "obsolete" (source).
What are the reasons for these decisions?
These APIs have been declared as "obsolete" for the usual reasons: they are old, not secure, not portable, have unspecified/undefined behavior, have tricky edge cases, better alternatives exist, etc.
Deprecation of APIs in Linux is generally done on a case-by-case basis; there is no general rule.
Why is stime() deprecated…
It's a non-standard function from SVr4 that nobody uses (on Linux). You should use clock_settime instead in every case.
…but not time()?
time() is a super standard function available everywhere, as it's the part of the C language standard. It will be used until the end of... time!
gettimeofday() offers higher resolution than time(), but the former rather than the latter was declared "obsolete"
gettimeofday() is a POSIX function, and POSIX standardized existing practices. After some time (POSIX Issue 7) clock_gettime() was invented with greater resolution and to be more portable. Because a better and safer interface exists, POSIX noted that gettimeofday() is obsolesced. I think the note is pretty self-explanatory to a developer:
APPLICATION USAGE
Applications should use the clock_gettime() function instead of the obsolescent gettimeofday() function.
In general, to find out why a particular API was deprecated, research about particular project history. Source code repositories offer commit history, standards, like POSIX or the C standard, come with "rationale", a separate document or included with the document, that explain the decisions.
For example, you can find out about stime() deprecation in glibc from this commit:
* The obsolete function stime is no longer available to newly linked
binaries and it has been removed from <time.h> header. This function
has been deprecated in favor of clock_settime.
Related
In regards to the thread safe functions in newer versions of the C standard library, is there a cross-platform way to tell if these are available via pre-processor definition? I am referring to functions such as localtime_r().
If there is not a standard way, what is the reliable way in GCC? [EDIT] Or posix systems with unistd.h?
There is no standard way to test that, which means there is no way to test it across all platforms. Tools like autoconf will create a tiny C program that calls this function and then try to compile and link it. It this works, looks like the function exists, if not, then it may not exist (or the compiler options are wrong and the appropriate CFLAGS need to be set).
So you have basically 6 options:
Require them to exist. Your code can only work on platforms where they exist; period. If they don't exist, compilation will fail, but that is not your problem, since the platform violates your minimum requirements.
Avoid using them. If you use the non-thread safe ones, maybe protected by a global lock (e.g. a mutex), it doesn't matter if they exist or not. Of course your code will then only work on platforms with POSIX mutexes, however, if a platform has no POSIX mutexes, it won't have POSIX threads either and if it has no POSIX threads (and I guess you are probably using POSIX threads w/o supporting any alternative), why would you have to worry about thread-safety in the first place?
Decide at runtime. Depending on the platform, either do a "weak link", so you can test at runtime if the function was found or not (a pointer to the function will point to NULL if it wasn't) or alternatively resolve the symbol dynamically using something like dlsym() (which is also not really portable, but widely supported in the Linux/UNIX world). However, in that case you need a fallback if the function is not found at runtime.
Use a tool like autoconf, some other tool with similar functionality, or your own configuration script to determine this prior to start of compilation (and maybe set preprocessor macros depending on result). In that case you will also need a fallback solution.
Limit usage to well known platforms. Whether this function is available on a certain platform is usually known (and once it is available, it won't go away in the future). Most platforms expose preprocessor macros to test what kind of platform that is and sometimes even which version. E.g. if you know that GNU/Linux, Android, Free/Open/NetBSD, Solaris, iOS and MacOS X all offer this function, test if you are compiling for one of these platforms and if yes, use it. If the code is compiled for another platform (or if you cannot determine what platform that is), it may or may not offer this function, but since you cannot say for sure, better be safe and use the fallback.
Let the user decide. Either always use the fallback, unless the user has signaled support or do it the other way round (which makes probably more sense), always assume it is there and in case compilation fails, offer a way the user can force your code into "compatibility mode", by somehow specifying that thread-safe-functions are not available (e.g. by setting an environment variable or by using a different make target). Of course this is the least convenient method for the (poor) user.
The compiler (Visual C++) always corrects me when I type flushall();
warning C4996: 'flushall': The POSIX name for this item is deprecated. Instead, use the ISO C++ conformant name: _flushall.
They both work for me, is there any difference?
This warning is nonsensical; flushall is not POSIX, and to my knowledge, never was. The correct ISO C way to flush all open stdio streams is fflush(NULL);.
To shed some more light on the issue, I believe this is a generic warning message Visual C uses for functions which are not part of the C standard, but which their standard library has for some minimal degree of compatibility. Most of these functions are things like open and read, and correspond in some vague way to the POSIX functions by the same name, and can be thought of as the lower-level primitives underlying stdio, etc. Some, like flushall, are not actually from POSIX, but just based on oddball functions copied from various legacy unices.
Since these functions are not actually part of the C (or C++) standards, and the C standard (and possibly also the C++ standard...?) reserves for the application identifiers which are not explicitly defined or reserved in the standard, it's non-conformant to expose in the standard headers names like open or flushall. POSIX gets around this by using feature test macros by which an application can make the namespace guarantees it wants from the implementation explict, but Microsoft instead took an approach of deprecating the POSIX-like names and offering an alternative set of functions, prefixed with underscores, which makes them part of the namespace reserved for the implementation. The warning is recommending that you use these Microsoft-specific names, so that your code would still compile if you turned on the options (probably controlled by macros of compiler switches) for a strict namespace conformance in the headers.
Unfortunately, writing code the Microsoft-recommended way with the underscore-prefixed names renders your code completely non-portable. Since these names are in the namespace reserved for the implementation, other platforms might happen to use the same names for functions which do completely different things, and being as they're reserved, you would not be allowed to replace or #define around them to remap them to other functions.
In short: I would find the warning flag that's generating this warning, and turn it off. Along with the one that spews FUD that such-and-such standard function is "insecure" and you should use the _s-suffixed function instead. But if the only function you need is fflushall(), simply replace it with fflush(NULL); and you're good to go.
This goes back to late 1988, back when Dave Cutler's team started development on Windows NT. The design goal was to create an operating system with three distinct api layers, Winapi, OS/2 and POSIX. POSIX was very new back then, the very first version was released in 1988 as well. It got included because it was listed as a requirement in a USA government standard, FIPS 151-2.
Back then the Unix Wars started to get serious. Pretty vicious with intentional differences in competing implementations. Main combatants were the Open Software Foundation, an industry group that feared Sun's increasing dominance and Unix International, a group around AT&T. That dust didn't settle until 1993 and the formation of the COSE alliance, now Open Group.
This makes the exact origin of flushall() pretty hard to trace, it was very much the wild wild west back then. Microsoft was also in the C compiler business so of course they released the tools to build programs that ran on the POSIX layer, including headers that declared the functions. So surely the time that flushall came about in their toolset. I don't have a copy anymore to check, destroyed by a leaky roof.
The NT Posix and OS/2 api layers never gained much traction, significantly overshadowed by Win32's runaway success. They were entirely dropped in 2001 with the XP release. Which, I think, was also around the time that they started deprecating the original Posix function names. Clearly it didn't make much sense anymore to keep these declarations around when they were no longer supported by the operating system. The Posix names are fairly awkward, short lower-case names in the global namespace cause many accidents.
They were however never completely removed, still documented to this day. Which is why you got the warning. Rather then choosing, do favor standard C library names, fflush().
Hi I'm need to jump from a place to another...
But I would like to know which is better to use, setjmp or ucontext, things like:
Are setjmp and ucontext portable?
My code is thread safe using these library?
Why use one instead another?
Which is fast and secure?
...(Someone please, can answer future question that I forgot to put here?)
Please give a little more information that I'm asking for, like examples or some docs...
I had searching on the web, but I only got exception handling in C like example of setjmp, and I got nothing about ucontex.h, I got that it was used for multitask, what's the difference of it and pthread?
Thanks a lot.
setjmp is portable (ISO C89 and C99) and ucontext (obsolescent in SUSv3 and removed from SUSv4/POSIX 2008) is not. However ucontext was considerably more powerful in specification. In practice, if you used nasty hacks with setjmp/longjmp and signal handlers and alternate signal handling stacks, you could make these just about as powerful as ucontext, but they were not "portable".
Neither should be used for multithreading. For that purpose POSIX threads (pthread functions). I have several reasons for saying this:
If you're writing threaded code, you might as well make it actually run concurrently. We're hitting the speed limits of non-parallel computing and future machines will be more and more parallel, so take advantage of that.
ucontext was removed from the standards and might not be supported in future OS's (or even some present ones?)
Rolling your own threads cannot be made transparent to library code you might want to use. It might break library code that makes reasonable assumptions about concurrency, locking, etc. As long as your multithreading is cooperative rather than async-signal-based there are probably not too many issues like this, but once you've gotten this deep into nonportable hacks things can get very fragile.
...and probably some more reasons I can't think of right now. :-)
On the portability matter, setjmp() is portable to all hosted C implementations; the <ucontext.h> functions are part of the XSI extensions to POSIX - this makes setjmp() significantly more portable.
It is possible to use setjmp() in a thread-safe manner. It doesn't make much sense to use the ucontext functions in a threaded program - you would use multiple threads rather than multiple contexts.
Use setjmp() if you want to quickly return from a deeply-nested function call (this is why you find that most examples show its use for exception handling). Use the ucontext functions for implementing user-space threads or coroutines (or don't use them at all).
The "fast and secure" question makes no sense. The implementations are typically as fast as it is practical to make them, but they perform different functions so cannot be directly compared (the ucontext functions do more work, so will typically be slightly slower).
Note that the ucontext functions are listed as obsolescent in the two most recent editions of POSIX. The pthreads threading functions should generally be used instead.
setjmp/longjmp are only intended to restore a "calling" context, so you can use it only to do a "fast exit" from a chain of subroutines. Different uses may or may not work depending on the system, but in general these functions are not intended to do this kind of things. So "ucontext" is better. Also have a look to "fibers" (native on Windows). Here a link to an article that may be helpful:
How to implement a practical fiber scheduler?
Bye!
The user thread functions in <ucontext.h> are deprecated because they use a deprecated C feature (they use a function declaration with empty parentheses for an argument).
Is there a standard replacement for them? I don't feel full-fledged threads are good at implementing cooperative threading.
If you really want to do something like what the ucontext.h functions allow, I would keep using them. Anything else will be less portable. Marking them obsolescent in POSIX seems to have been a horrible mistake of pedantry by someone on the committee. POSIX itself requires function pointers and data pointers to be the same size and for function pointers to be representable cast to void *, and C itself requires a cast between function pointer types and back to be round-trip safe, so there are many ways this issue could have been solved.
There is one real problem, that converting the int argc, ... passed into makecontext into a form to pass to the function cannot be done without major assistance from the compiler unless the calling convention for variadic and non-variadic functions happens to be the same (and even then it's rather questionable whether it can be done robustly). This problem however could have been solved simply by deprecating the use of makecontext in any form other than makecontext(ucp, func, 1, (void *)arg);.
Perhaps a better question though is why you think ucontext.h functions are the best way to handle threading. If you do want to go with them, I might suggest writing a wrapper interface that you can implement either with ucontext.h or with pthreads, then comparing the performance and bloat. This will also have the advantage that, should future systems drop support for ucontext.h, you can simply switch to compiling with the pthread-based implementation and everything will simply work. (By then, the bloat might be less important, the benefit of multi-core/SMP will probably be huge, and hopefully pthread implementations will be less bloated.)
Edit (based on OP's request): To implement "cooperative threading" with pthreads, you need condition variables. Here's a decent pthreads tutorial with information on using them:
https://computing.llnl.gov/tutorials/pthreads/#ConditionVariables
Your cooperative multitasking primitive of "hand off execution to thread X" would go something like:
self->flag = 0;
other_thread->flag = 1;
pthread_mutex_lock(other_thread->mutex);
pthread_cond_signal(other_thread->cond);
pthread_mutex_unlock(other_thread->mutex);
pthread_mutex_lock(self->mutex);
while (!self->flag)
pthread_cond_wait(self->cond, self->mutex);
pthread_mutex_unlock(self->mutex);
Hope I got that all right; at least the general idea is correct. If anyone sees mistakes please comment so I can fix it. Half of the locking (other_thread's mutex) is probably entirely unnecessary with this sort of usage, so you could perhaps make the mutex a local variable in the task_switch function. All you'd really be doing is using pthread_cond_wait and pthread_cond_signal as "go to sleep" and "wake up other thread" primitives.
For what it's worth, there's a Boost.Context library that was recently accepted and needs only to be merged into an official Boost release. Boost.Context addresses the same use cases as the POSIX ucontext family: low-overhead cooperative context switching. The author has taken pains with performance issues.
No, there is no standard replacement for them.
You options are
continue to use <ucontext.h>even though they contain obsolete C.
switch to pthreads
write your own co-thread library
use an existing (and possibly not-so-portable) co-thread library such as http://swtch.com/libtask/ , though many of such libraries are implemented on top of ucontext.h
The Open Group Base Specifications Issue 6
IEEE Std 1003.1, 2004 Edition
Still lists makecontext() and swapcontext() with the same deprecated syntax. I have not seen anything more recent.
Just as in title. Is suspect it is, but I couldn't find it anywhere explicitly stated. And for this property I wouldn't like to rely on speculations.
If you use the multithreaded version of the CRT, all functions are thread safe, because any thread-specific information is stored in TLS. rand_s actually doesn't use state information in the first place, since it just calls an OS API, so question of thread-safety doesn't arise for rand_s. rand(), however depends on a seed value to generate a random number.
Chris said: rand() is not thread-safe because its internal state is static, but rand_s() should be thread-safe, however.
Jeff added however that with the multithreaded version of MSVCRT, rand()'s state is held in thread-local storage, so it's okay still.
Visual Studio comes with the source to the runtime library. While some of it can be rather painful to wade through, rand_s() is pretty simple.
All rand_s() does is call SystemFunction036() in ADVAPI32.DLL to get the random value. Anything in ADVAPI32.DLL should be thread-safe.
For its part, rand_s() gets the pointer to that function in a thread-safe manner.
I don't know if rand_s is thread-safe, but it seems like it probably is, since it seems to make a round-trip to the OS for entropy. (as long as you link to the VC++ multi-thread CRT, all bets are off if you link to the single-thread one)
If it's supported by windows CRT, you can try a call to rand_r which is the posix reentrant version of rand. OR even better boost::random, if you're already using boost.
considering how pervasive multi-threading will be soon, no one should be using rand() anymore in new code - always try to use rand_r/rand_s/boost/various platform-dependent secure rands/etc.
I can't think of any reason why rand_s() or even rand() wouldn't be thread safe.