POSIX: Difference between revisions

From miki
Jump to navigation Jump to search
 
(9 intermediate revisions by the same user not shown)
Line 1: Line 1:
== PThreads ==
== PThreads ==

=== General Information ===


Links:
Links:


* [https://computing.llnl.gov/tutorials/pthreads/ POSIX Threads Programming], excellent introduction to pthreads, by Blaise Barney, at Lawrence Livermore National Laboratory.
* [https://computing.llnl.gov/tutorials/pthreads/ POSIX Threads Programming], excellent introduction to pthreads, by Blaise Barney, at Lawrence Livermore National Laboratory.
* [http://www.advancedlinuxprogramming.com/alp-folder/alp-ch04-threads.pdf Advanced Linux Programming Ch 4 — Threads]
* [http://www.yolinux.com/TUTORIALS/LinuxTutorialPosixThreads.html POSIX thread (pthread) libraries]
* [http://en.wikipedia.org/wiki/POSIX_Threads POSIX Threads] (wikipedia)
* [http://en.wikipedia.org/wiki/POSIX_Threads POSIX Threads] (wikipedia)


Manual page:
;Advices
* [http://localhost/cgi-bin/dwww?type=runman&location=pthreads/7 pthreads (7)]
* For portability, always create ''joinable'' or ''detachable'' threads by setting explicitly the thread attribute (using <code>pthread_attr_getdetachstate</code>). This provides portability as not all implementations may create threads as joinable by default.

=== Portability ===
; Joinable / detachable state
: For portability, always create ''joinable'' or ''detachable'' threads by setting explicitly the thread attribute (using <code>pthread_attr_getdetachstate</code>). This provides portability as not all implementations may create threads as joinable by default.

=== Linux vs. POSIX manual pages ===
Most manual pages on pthreads are available as either standard linux manual pages or as extract from the POSIX programmer manual.

For instance:
* [http://localhost/cgi-bin/dwww?type=runman&location=pthread_cond_signal/3posix pthread_cond_signal(3posix)]
* [http://localhost/cgi-bin/dwww?type=runman&location=pthread%5fcond%5fsignal/3 pthread_cond_signal(3)]

Both versions are worth reading.

=== Create threads ===
See [http://localhost/cgi-bin/dwww?type=runman&location=pthread%5fcreate/3 pthread_create(3)].

=== Conditional variables ===
See
* pthread_cond_init
* pthread_cond_destroy
* pthread_cond_signal
* pthread_cond_broadcast
* pthread_cond_wait
* pthread_cond_timedwait

Note that these functions are '''NOT''' ''signal-async safe'' (see [http://localhost/cgi-bin/dwww?type=runman&location=signal/7], [http://localhost/cgi-bin/dwww?type=runman&location=pthread%5fcond%5fsignal/3]). They '''CANNOT''' be called safely from a async signal handler (like ''SIGIO'' signal handler).

=== Thread-Local Data ===
* Using ''thread-specific data'' area foreseen by POSIX, which requires first creating a key that is later used to set or get thread-specific data attached to that key (see [http://www.advancedlinuxprogramming.com/alp-folder/alp-ch04-threads.pdf Advanced Linux Programming - Ch 4])
* Using keyword '''__thread''', see [http://www.akkadia.org/drepper/tls.pdf http://www.akkadia.org/drepper/tls.pdf] (not available in all compiler, not standard C99 [http://stackoverflow.com/questions/6869391/using-thread-in-c99]).

<source lang=c>
// Compile this code with : gcc local.c -o local -lpthread

#include <stdio.h>
#include <unistd.h>
#include <pthread.h>

static __thread int myint;
static int globalint = 0;

void * handler(void *arg)
{
myint = ++globalint; // thread unsafe - should use a mutex
while(1) {
printf("myint is %d\n", myint);
sleep(1);
}
}

int main (int argc, char **argv)
{
pthread_t p1,p2;

pthread_create(&p1, NULL, handler, NULL);
pthread_create(&p2, NULL, handler, NULL);

pause();
return 0;
}
</source>

=== Debugging ===
See [[Debugging]] page.

== Signals ==

Manual pages:
* [http://localhost/cgi-bin/dwww?type=runman&location=signal/7 signal(7)]

=== Async-Signal Safety ===
''Async-signal safety'' is similar to thread safety. Since asynchronous signals (like SIGINT or SIGIO) may happen anytime, and this interrupt any function, it might not be same to call the interrupted function again (concurrently) from with the signal handler. POSIX defines the set of system functions that are ''async-signal safe'' (see [http://localhost/cgi-bin/dwww?type=runman&location=signal/7 signal(7)]).


Note that pthread functions are '''not''' in the list, so it is not quite clear how to wake up another suspended thread from within an async-signal handler.

Some ideas:
* Use ''signals'' to wake up the suspended thread. This assumes that the suspended thread is waiting on signals (see [http://localhost/cgi-bin/dwww?type=runman&location=sigtimedwait/2 sigtimedwait(2)], [http://localhost/cgi-bin/dwww?type=runman&location=sigtimedwait/3posix sigtimedwait(3)]).
* Calling <code>pthread_cond_signal</code> is unsafe from signal handler (see [http://localhost/cgi-bin/dwww?type=runman&location=pthread%5fcond%5fwait/3]), because handler thread may dead-lock if it interrupts a ''[http://localhost/cgi-bin/dwww?type=runman&location=pthread%5fcond%5fwait/3 pthread_cond]'' functions (system may use a semaphore internally). Maybe is it possible to suspend the processing of async-signal before so that they do not interrupt these critical sections? (see for instance [http://localhost/cgi-bin/dwww?type=runman&location=sigsuspend/3posix sigsuspend(3posix)]).
* Use '''[http://localhost/cgi-bin/dwww?type=runman&location=sem_post/3posix sem_post(3posix)]'''. This is the only thread synchronization function provided by POSIX threads that is async-signal safe ([http://www2.themanualpage.org/man/man3/sem_post.3.php3]). See below for an example.
* Use sigwait. This follows Butenhof's recommendation (see [http://www.linuxquestions.org/questions/programming-9/sigio-sigaction-wakes-sleep-up-early-738720/]):
::''Always use sigwait to work with asynchronous signals within threaded programs.''
: An example from [https://agora.cs.illinois.edu/download/attachments/38308138/lect15.pdf]:
{|
|valign="top"|
'''High priority I/O thread'''
<source lang=c>
void* thread_I/O (void * arg)
{
int signal;
sigset_t look_for_these; // this contains the signal we wait for
sigemptyset(&look_for_these);
sigaddset(& look_for_these, SIGALARM);
// create the timer
// initialize the timer (SIGALARM will be sent each time the timer expires!)
while (1) {
sigwait(& look_for_these, &signal); // waits for SIGALARM
if ( signal == SIGALARM) {
do_your_device_I/O();
// use global variables to communicate between I/O
// and worker threads
sem_post (& sync_semaphore);
}
}
}
</source>
|
'''Low priority worker thread'''
<source lang=c>
sem_t sync_semaphore;
int main()
{
pthread_t thread_id;
sigset_t process_mask; // this is the process mask
sigemptyset(&process_mask);
sigaddset(& process_mask, SIGALARM);
pthread_sigmask(SIG_BLOCK, & process_mask, NULL);
sem_init (&sync_semaphore, 0, 0) // semaphore is initially locked!
// create the I/O thread
pthread_create (&thread_id, NULL, thread_I/O, NULL);
while (1) {
sem_wait (& sync_semaphore);
// sync_semaphore is a shared semaphore that allows
//the worker and I/O threads to synchronize their actions!
read_the_data_from_buffer();
do_your_computation();
put_result_in_output_buffer();
// make the I/O thread code as small as possible to reduce jitter.
}
}
</source>
|}

=== Some interesting read ===
; [http://elliotth.blogspot.be/2011/05/signal2-versus-sigaction2.html signal(2) versus sigaction(2)]
: Some ideas on how to have multiple threads blocking on I/O and being able to cancel them.
; Book &mdash; ''Programming with POSIX Threads'', David R. Butenhof, Ed. Addison Wesley

Latest revision as of 16:39, 5 November 2012

PThreads

General Information

Links:

Manual page:

Portability

Joinable / detachable state
For portability, always create joinable or detachable threads by setting explicitly the thread attribute (using pthread_attr_getdetachstate). This provides portability as not all implementations may create threads as joinable by default.

Linux vs. POSIX manual pages

Most manual pages on pthreads are available as either standard linux manual pages or as extract from the POSIX programmer manual.

For instance:

Both versions are worth reading.

Create threads

See pthread_create(3).

Conditional variables

See

  • pthread_cond_init
  • pthread_cond_destroy
  • pthread_cond_signal
  • pthread_cond_broadcast
  • pthread_cond_wait
  • pthread_cond_timedwait

Note that these functions are NOT signal-async safe (see [1], [2]). They CANNOT be called safely from a async signal handler (like SIGIO signal handler).

Thread-Local Data

// Compile this code with : gcc local.c -o local -lpthread

#include <stdio.h>
#include <unistd.h>
#include <pthread.h>

static __thread int myint;
static int globalint = 0;

void * handler(void *arg)
{
    myint = ++globalint;                              // thread unsafe - should use a mutex
    while(1) {
        printf("myint is %d\n", myint);
        sleep(1);
    }
}

int main (int argc, char **argv)
{
    pthread_t p1,p2;

    pthread_create(&p1, NULL, handler, NULL);
    pthread_create(&p2, NULL, handler, NULL);

    pause();
    return 0;
}

Debugging

See Debugging page.

Signals

Manual pages:

Async-Signal Safety

Async-signal safety is similar to thread safety. Since asynchronous signals (like SIGINT or SIGIO) may happen anytime, and this interrupt any function, it might not be same to call the interrupted function again (concurrently) from with the signal handler. POSIX defines the set of system functions that are async-signal safe (see signal(7)).


Note that pthread functions are not in the list, so it is not quite clear how to wake up another suspended thread from within an async-signal handler.

Some ideas:

  • Use signals to wake up the suspended thread. This assumes that the suspended thread is waiting on signals (see sigtimedwait(2), sigtimedwait(3)).
  • Calling pthread_cond_signal is unsafe from signal handler (see [4]), because handler thread may dead-lock if it interrupts a pthread_cond functions (system may use a semaphore internally). Maybe is it possible to suspend the processing of async-signal before so that they do not interrupt these critical sections? (see for instance sigsuspend(3posix)).
  • Use sem_post(3posix). This is the only thread synchronization function provided by POSIX threads that is async-signal safe ([5]). See below for an example.
  • Use sigwait. This follows Butenhof's recommendation (see [6]):
Always use sigwait to work with asynchronous signals within threaded programs.
An example from [7]:

High priority I/O thread

void* thread_I/O (void * arg)
{
  int signal;
  sigset_t look_for_these; // this contains the signal we wait for
  sigemptyset(&look_for_these);
  sigaddset(& look_for_these, SIGALARM);
  // create the timer
  // initialize the timer (SIGALARM will be sent each time the timer expires!)
  while (1) {
    sigwait(& look_for_these, &signal); // waits for SIGALARM
    if ( signal == SIGALARM) {
      do_your_device_I/O();
      // use global variables to communicate between I/O
      // and worker threads
      sem_post (& sync_semaphore);
    }
  }
}

Low priority worker thread

sem_t sync_semaphore;
int main()
{
  pthread_t thread_id;
  sigset_t process_mask; // this is the process mask
  sigemptyset(&process_mask);
  sigaddset(& process_mask, SIGALARM);
  pthread_sigmask(SIG_BLOCK, & process_mask, NULL);
  sem_init (&sync_semaphore, 0, 0) // semaphore is initially locked!
  // create the I/O thread
  pthread_create (&thread_id, NULL, thread_I/O, NULL);
  while (1) {
    sem_wait (& sync_semaphore);
    // sync_semaphore is a shared semaphore that allows
    //the worker and I/O threads to synchronize their actions!
    read_the_data_from_buffer();
    do_your_computation();
    put_result_in_output_buffer();
    // make the I/O thread code as small as possible to reduce jitter.
  }
}

Some interesting read

signal(2) versus sigaction(2)
Some ideas on how to have multiple threads blocking on I/O and being able to cancel them.
Book — Programming with POSIX Threads, David R. Butenhof, Ed. Addison Wesley