Lecture 12 Overview. UDP Connected mode A UDP socket can be used in a call to connect() This simply tells the O.S. the address of the peer No handshake.

Slides:



Advertisements
Similar presentations
Threads. Readings r Silberschatz et al : Chapter 4.
Advertisements

Threads Programming Thread creation Synchronization.
CS162B: POSIX Threads Jacob Chan. Objectives ▪ Review on fork() and exec() – Some issues on forking and exec-ing ▪ POSIX Threads ▪ Lab 8.
I/O Multiplexing Road Map: 1. Motivation 2. Description of I/O multiplexing 3. Scenarios to use I/O multiplexing 4. I/O Models  Blocking I/O  Non-blocking.
Lecture 6 TCP Socket Programming CPE 401 / 601 Computer Network Systems slides are modified from Dave Hollinger.
Lecture 17 Client/Server Programming Chat CPE 401 / 601 Computer Network Systems slides are modified from Dave Hollinger.
Lecture 16 Overview. Creating a TCP socket int bind(int sockfd, const struct sockaddr *myaddr, socklen_t addrlen); int mysock; struct sockaddr_in myaddr;
Computer Architecture II 1 Computer architecture II Programming: POSIX Threads OpenMP.
TDC561 Network Programming Camelia Zlatea, PhD Week 3: Unix Asynchronous Events; Signals and Alarms API.
Precept 3 COS 461. Concurrency is Useful Multi Processor/Core Multiple Inputs Don’t wait on slow devices.
Fork Fork is used to create a child process. Most network servers under Unix are written this way Concurrent server: parent accepts the connection, forks.
1 Data Communications and Networking Socket Programming Part II: Design of Server Software Reference: Internetworking with TCP/IP, Volume III Client-Server.
8-1 JMH Associates © 2004, All rights reserved Windows Application Development Chapter 10 - Supplement Introduction to Pthreads for Application Portability.
Lecture 18 Threaded Programming CPE 401 / 601 Computer Network Systems slides are modified from Dave Hollinger.
Threads© Dr. Ayman Abdel-Hamid, CS4254 Spring CS4254 Computer Network Architecture and Programming Dr. Ayman A. Abdel-Hamid Computer Science Department.
Lecture 8 UDP Sockets & I/O Multiplexing
Server Design Discuss Design issues for Servers Review Server Creation in Linux.
Netprog Threads Programming1 Threads Programming Refs: Chapter 23.
LWIP TCP/IP Stack 김백규.
Server Sockets: A server socket listens on a given port Many different clients may be connecting to that port Ideally, you would like a separate file descriptor.
10/16/ Realizing Concurrency using the thread model B. Ramamurthy.
B. RAMAMURTHY 10/24/ Realizing Concurrency using the thread model.
Concurrency. Readings r Tanenbaum and van Steen: r Coulouris: Chapter 6 r cs402 web page links r UNIX Network Programming by W. Richard Stevens.
June-Hyun, Moon Computer Communications LAB., Kwangwoon University Chapter 26 - Threads.
CS 346 – Chapter 4 Threads –How they differ from processes –Definition, purpose Threads of the same process share: code, data, open files –Types –Support.
Threads and Thread Control Thread Concepts Pthread Creation and Termination Pthread synchronization Threads and Signals.
Programming with POSIX* Threads Intel Software College.
Chapter 2 Applications and Layered Architectures Sockets.
CSCE 515: Computer Network Programming TFTP + Errors Wenyuan Xu Department of Computer Science and Engineering.
CS333 Intro to Operating Systems Jonathan Walpole.
1 I/O Multiplexing We often need to be able to monitor multiple descriptors:We often need to be able to monitor multiple descriptors: –a generic TCP client.
CSCE 515: Computer Network Programming Select Wenyuan Xu Department of Computer Science and Engineering.
CSCE 515: Computer Network Programming UDP Socket Wenyuan Xu Department of Computer Science and Engineering.
Threads CSCE Thread Motivation Processes are expensive to create. Context switch between processes is expensive Communication between processes.
S -1 Posix Threads. S -2 Thread Concepts Threads are "lightweight processes" –10 to 100 times faster than fork() Threads share: –process instructions,
Threads and Locking Ioctl operations. Threads Lightweight processes What’s wrong with processes? –fork() is expensive – 10 to 100 times slower –Inter.
Threads Chapter 26. Threads Light-weight processes Each process can have multiple threads of concurrent control. What’s wrong with processes? fork() is.
Pthreads.
Silberschatz, Galvin and Gagne  2002 Modified for CSCI 399, Royden, Operating System Concepts Operating Systems Lecture 14 Threads 2 Read Ch.
Operating Systems CSE 411 CPU Management Sept Lecture 10 Instructor: Bhuvan Urgaonkar.
12/22/ Thread Model for Realizing Concurrency B. Ramamurthy.
Programming with UDP – II Covered Subjects: Creating UDP sockets Client Server Sending data Receiving data Connected mode.
© Janice Regan, CMPT 300, May CMPT 300 Introduction to Operating Systems Operating Systems Processes and Threads.
Socket Programming. Computer Science, FSU2 Interprocess Communication Within a single system – Pipes, FIFOs – Message Queues – Semaphores, Shared Memory.
PThread Synchronization. Thread Mechanisms Birrell identifies four mechanisms commonly used in threading systems –Thread creation –Mutual exclusion (mutex)
Netprog: Client/Server Issues1 Issues in Client/Server Programming Refs: Chapter 27.
Thread Basic Thread operations include thread creation, termination, synchronization, data management Threads in the same process share:  Process address.
Lecture 3 TCP and UDP Sockets CPE 401 / 601 Computer Network Systems slides are modified from Dave Hollinger.
Client/Server Design Issues Based on Java Network Programming and Distributed Computing, Chapter 6 Also Online Java Tutorial, Sun.
2.2 Threads  Process: address space + code execution  There is no law that states that a process cannot have more than one “line” of execution.  Threads:
1 UDP Sockets Programming Creating UDP sockets.Creating UDP sockets. –Client –Server Sending data.Sending data. Receiving data.Receiving data. Connected.
7/9/ Realizing Concurrency using Posix Threads (pthreads) B. Ramamurthy.
Case Study: Pthread Synchronization Dr. Yingwu Zhu.
1 Issues in Client/Server Refs: Chapter 27 Case Studies RFCs.
Threads Some of these slides were originally made by Dr. Roger deBry. They include text, figures, and information from this class’s textbook, Operating.
Threads Threads.
Netprog: Threads Programming
CS399 New Beginnings Jonathan Walpole.
Realizing Concurrency using Posix Threads (pthreads)
Lecture 4 Socket Programming Issues
UDP Sockets Programming
Realizing Concurrency using the thread model
Lecture 11 Overview.
Lecture 17 Overview.
Issues in Client/Server Programming
Realizing Concurrency using Posix Threads (pthreads)
Realizing Concurrency using the thread model
Server-side Programming CSE 333 Summer 2018
Realizing Concurrency using Posix Threads (pthreads)
I/O Multiplexing We often need to be able to monitor multiple descriptors: a generic TCP client (like telnet) need to be able to handle unexpected situations,
Presentation transcript:

Lecture 12 Overview

UDP Connected mode A UDP socket can be used in a call to connect() This simply tells the O.S. the address of the peer No handshake is made to establish that the peer exists No data of any kind is sent on the network as a result of calling connect() on a UDP socket 2 CPE 401/601 Lecture 12 : Socket Programming Issues

Connected UDP Once a UDP socket is connected: – can use sendto() with a null dest address – can use write() and send() – can use read() and recv() only datagrams from the peer will be returned – Asynchronous errors will be returned to the process 3 OS Specific, some won’t do this! CPE 401/601 Lecture 12 : Socket Programming Issues

Asynchronous Errors What happens if a client sends data to a server that is not running? – ICMP “port unreachable” error is generated by receiving host and sent to sending host – The ICMP error may reach the sending host after sendto() has already returned! – The next call dealing with the socket could return the error 4 CPE 401/601 Lecture 12 : Socket Programming Issues

I/O Multiplexing We often need to be able to monitor multiple descriptors: – a generic TCP client (like telnet) – a server that handles both TCP and UDP – Client that can make multiple concurrent requests browser 5 CPE 401/601 Lecture 12 : I/O Multiplexing

Example - generic TCP client Input from standard input should be sent to a TCP socket Input from a TCP socket should be sent to standard output How do we know when to check for input from each source? 6 STDIN STDOUT TCP SOCKET CPE 401/601 Lecture 12 : I/O Multiplexing

Options Use multiple processes/threads Use nonblocking I/O – use fcntl() to set O_NONBLOCK Use alarm and signal handler to interrupt slow system calls Use functions that support checking of multiple input sources at the same time 7 CPE 401/601 Lecture 12 : I/O Multiplexing

Non blocking I/O Tell kernel not to block a process if I/O requests can not be completed use fcntl() to set O_NONBLOCK: int flags; flags = fcntl(sock,F_GETFL,0); fcntl(sock,F_SETFL,flags | O_NONBLOCK); Now calls to read() (and other system calls) will return an error and set errno to EWOULDBLOCK 8 CPE 401/601 Lecture 12 : I/O Multiplexing

Non blocking I/O while (! done) { if ( (n=read(STDIN_FILENO,…)<0)) if (errno != EWOULDBLOCK) /* ERROR */ else write(tcpsock,…) if ( (n=read(tcpsock,…)<0)) if (errno != EWOULDBLOCK) /* ERROR */ else write(STDOUT_FILENO,…) } 9 CPE 401/601 Lecture 12 : I/O Multiplexing

The problem with nonblocking I/O Using blocking I/O allows the OS to put your process to sleep when nothing is happening – Once input arrives, the OS will wake up your process and read() (or whatever) will return With nonblocking I/O, the process will chew up all available processor time!!! 10 CPE 401/601 Lecture 12 : I/O Multiplexing

Using alarms signal(SIGALRM, sig_alrm); alarm(MAX_TIME); read(STDIN_FILENO,…);... signal(SIGALRM, sig_alrm); alarm(MAX_TIME); read(tcpsock,…); A function you write CPE 401/601 Lecture 12 : I/O Multiplexing

“Alarming” Issues What will happen to the response time ? What is the ‘right’ value for MAX_TIME? 12 CPE 401/601 Lecture 12 : I/O Multiplexing

Select() The select() system call allows us to use blocking I/O on a set of descriptors – file, socket, … We can ask select to notify us when data is available for reading on either STDIN or a socket 13 CPE 401/601 Lecture 12 : I/O Multiplexing

select() int select( int maxfd, fd_set *readset, fd_set *writeset, fd_set *excepset, const struct timeval *timeout); maxfd: highest number assigned to a descriptor readset: set of descriptors we want to read from writeset: set of descriptors we want to write to excepset: set of descriptors to watch for exceptions timeout: maximum time select should wait 14 CPE 401/601 Lecture 12 : I/O Multiplexing

Using select() Create fd_set Clear the whole thing with FD_ZERO Add each descriptor you want to watch using FD_SET Call select when select returns, use FD_ISSET to see if I/O is possible on each descriptor 15 CPE 401/601 Lecture 12 : I/O Multiplexing

System Calls and Errors In general, systems calls return a negative number to indicate an error – We often want to find out what error – Servers generally add this information to a log – Clients generally provide some information to the user 16 CPE 401/601 Lecture 12 : Error Handling

What is fatal? How do you know what should be a fatal error? – Common sense – If the program can continue – it should – if a server can't create a socket, or can't bind to it's port there is no sense continuing… 17 CPE 401/601 Lecture 12 : Error Handling

extern int errno; Whenever an error occurs, system calls set the value of the global variable errno – You can check errno for specific errors errno is valid only after a system call has returned an error – System calls don't clear errno on success – If you make another system call you may lose the previous value of errno printf makes a call to write! 18 CPE 401/601 Lecture 12 : Error Handling

General Strategies Include code to check for errors after every system call Develop "wrapper functions" that do the checking for you Develop layers of functions, each hides some of the error-handling details 19 CPE 401/601 Lecture 12 : Error Handling

Wrappers are great! Wrappers like those used in the text can make code much more readable There are always situations in which you cannot use the wrappers – Sometimes system calls are "interrupted" (EINTR) this is not always a fatal error ! 20 CPE 401/601 Lecture 12 : Error Handling

Another approach Instead of simple wrapper functions, you might develop a layered system The idea is to "hide" the sockaddr and error handling details behind a few custom functions: – int tcp_client(char *server, int port); – int tcp_server(int port); 21 CPE 401/601 Lecture 12 : Error Handling

Layers and Code Re-use Developing general functions that might be re-used in other programs is obviously "a good thing" Layering is beneficial even if the code is not intended to be re-used: – hide error-handling from "high-level" code – hide other details – often makes debugging easier 22 CPE 401/601 Lecture 12 : Error Handling

The Best Approach to handling errors There is no best approach Do what works for you Make sure you check all system calls for errors! – Not checking can lead to security problems! – Not checking can lead to bad grades on assignments! 23 CPE 401/601 Lecture 12 : Error Handling

Lecture 13 Client/Server Programming CPE 401 / 601 Computer Network Systems slides are modified from Dave Hollinger

Issues in Client/Server Programming Identifying the Server Looking up an IP address Looking up a well known port name Specifying a local IP address UDP/TCP client design CPE 401/601 Lecture 13 : Client/Server Issues 25

Identifying the Server Options: – hard-coded into the client program – require that the user identify the server – read from a configuration file – use a separate protocol/network service to lookup the identity of the server. CPE 401/601 Lecture 13 : Client/Server Issues 26

Identifying a TCP/IP server Need an IP address, protocol and port – We often use host names instead of IP addresses – usually the protocol is not specified by the user UDP vs. TCP – often the port is not specified by the user CPE 401/601 Lecture 13 : Client/Server Issues 27

Services and Ports Many services are available via “well known” addresses (names) There is a mapping of service names to port numbers: struct *servent getservbyname( char *service, char *protocol ); servent->s_port is the port number in network byte order CPE 401/601 Lecture 13 : Client/Server Issues 28

Specifying a Local Address When a client creates and binds a socket, it must specify a local port and IP address Typically clients don’t care what port it is on: haddr->port = htons(0); CPE 401/601 Lecture 13 : Client/Server Issues 29 give me any available port !

Local IP address A client can also ask the operating system to take care of specifying the local IP address: haddr->sin_addr.s_addr= htonl(INADDR_ANY); CPE 401/601 Lecture 13 : Client/Server Issues 30 Give me the appropriate address

UDP Client Design Establish server address (IP and port) Allocate a socket Specify that any valid local port and IP address can be used Communicate with server (send, recv) Close the socket CPE 401/601 Lecture 13 : Client/Server Issues 31

Connected mode UDP A UDP client can call connect() to establish the address of the server The UDP client can then use read() and write() or send() and recv() A UDP client using a connected mode socket can only talk to one server – using the connected-mode socket CPE 401/601 Lecture 13 : Client/Server Issues 32

TCP Client Design Establish server address (IP and port) Allocate a socket Specify that any valid local port and IP address can be used Call connect() Communicate with server (read, write) Close the connection CPE 401/601 Lecture 13 : Client/Server Issues 33

Closing a TCP socket Many TCP based application protocols support – multiple requests and/or – variable length requests over a single TCP connection How does the server known when the client is done ? – and it is OK to close the socket ? CPE 401/601 Lecture 13 : Client/Server Issues 34

Partial Close One solution is for the client to shut down only it’s writing end of the socket shutdown() system call provides this function shutdown(int s, int direction); – direction can be 0 to close the reading end or 1 to close the writing end – shutdown sends info to the other process! CPE 401/601 Lecture 13 : Client/Server Issues 35

TCP sockets programming Common problem areas: – null termination of strings – reads don’t correspond to writes – synchronization (including close()) – ambiguous protocol CPE 401/601 Lecture 13 : Client/Server Issues 36

TCP Reads Each call to read() on a TCP socket returns any available data – up to a maximum TCP buffers data at both ends of the connection You must be prepared to accept data 1 byte at a time from a TCP socket! CPE 401/601 Lecture 13 : Client/Server Issues 37

Server Design CPE 401/601 Lecture 13 : Client/Server Issues 38 Iterative Small, fixed size requests Easy to program Iterative Small, fixed size requests Easy to program Concurrent Large or variable size requests Harder to program Typically uses more system resources Concurrent Large or variable size requests Harder to program Typically uses more system resources

Server Design CPE 401/601 Lecture 13 : Client/Server Issues 39 Connection-Oriented EASY TO PROGRAM transport protocol handles the tough stuff. requires separate socket for each connection. Connection-Oriented EASY TO PROGRAM transport protocol handles the tough stuff. requires separate socket for each connection. Connectionless less overhead no limitation on number of clients Connectionless less overhead no limitation on number of clients

Server Design CPE 401/601 Lecture 13 : Client/Server Issues 40 Iterative Connectionless Iterative Connectionless Iterative Connection-Oriented Iterative Connection-Oriented Concurrent Connection-Oriented Concurrent Connection-Oriented Concurrent Connectionless Concurrent Connectionless

Statelessness State: Information that a server maintains about the status of ongoing client interactions Connectionless servers that keep state information must be designed carefully! CPE 401/601 Lecture 13 : Client/Server Issues 41 Messages can be duplicated!

The Dangers of Statefullness Clients can go down at any time Client hosts can reboot many times The network can lose messages The network can duplicate messages CPE 401/601 Lecture 13 : Client/Server Issues 42

Concurrent Server Design Alternatives One child per client Spawn one thread per client Preforking multiple processes Prethreaded Server CPE 401/601 Lecture 13 : Client/Server Issues 43

One child per client Traditional Unix server: – TCP: after call to accept(), call fork() – UDP: after recvfrom(), call fork() – Each process needs only a few sockets – Small requests can be serviced in a small amount of time Parent process needs to clean up after children!!!! – call wait() CPE 401/601 Lecture 13 : Client/Server Issues 44

One thread per client Almost like using fork – call pthread_create instead Using threads makes it easier to have sibling processes share information – less overhead Sharing information must be done carefully – use pthread_mutex CPE 401/601 Lecture 13 : Client/Server Issues 45

Prefork()’d Server Creating a new process for each client is expensive We can create a bunch of processes, each of which can take care of a client Each child process is an iterative server CPE 401/601 Lecture 13 : Client/Server Issues 46

Prefork()’d TCP Server Initial process creates socket and binds to well known address. Process now calls fork() a bunch of times All children call accept() The next incoming connection will be handed to one child CPE 401/601 Lecture 13 : Client/Server Issues 47

Preforking Having too many preforked children can be bad Using dynamic process allocation instead of a hard-coded number of children can avoid problems Parent process just manages the children – doesn’t worry about clients CPE 401/601 Lecture 13 : Client/Server Issues 48

Sockets library vs. system call A preforked TCP server won’t always work if sockets is not part of the kernel – calling accept() is a library call, not an atomic operation We can get around this by making sure only one child calls accept() at a time using some locking scheme CPE 401/601 Lecture 13 : Client/Server Issues 49

Prethreaded Server Same benefits as preforking Can also have the main thread do all the calls to accept() – and hand off each client to an existing thread CPE 401/601 Lecture 13 : Client/Server Issues 50

What’s the best server design? Many factors: – expected number of simultaneous clients – Transaction size time to compute or lookup the answer – Variability in transaction size – Available system resources perhaps what resources can be required in order to run the service CPE 401/601 Lecture 13 : Client/Server Issues 51

Server Design It is important to understand the issues and options Knowledge of queuing theory can be a big help You might need to test a few alternatives to determine the best design CPE 401/601 Lecture 13 : Client/Server Issues 52

Threaded Programming

Threads vs. Processes Creation of a new process using fork is expensive –Time –Memory A thread does not require lots of memory or startup time –called a lightweight process Threads Programming 54

fork() Process A Global Variables Code Stack Process B Global Variables Code Stack fork()

Process A Thread 1 Global Variables Code Stack Process A Thread 2 Stack pthread_create()

Multiple Threads Each process can include many threads. All threads of a process share: – memory program code and global data – open file/socket descriptors – signal handlers and signal dispositions – working environment current directory, user ID, etc. Threads Programming 57

Thread-Specific Resources Each thread has it’s own: –Thread ID (integer) –Stack, Registers, Program Counter – errno Threads within the same process can communicate using shared memory. –Must be done carefully! Threads Programming 58

Posix Threads We will focus on Posix Threads –most widely supported threads programming API. Solaris –you need to link with “-lpthread” On many systems, this also forces the compiler to link in re-entrant libraries –instead of plain C libraries Threads Programming 59

Threads Programming 60 Thread Creation pthread_create( pthread_t *tid, const pthread_attr_t *attr, void *(*func)(void *), void *arg ); func is the function to be called. When func() returns the thread is terminated

Threads Programming 61 pthread_create() The return value is 0 for OK. – positive error number on error Does not set errno !!! Thread ID is returned in tid

pthread_t *tid The book says you can specify NULL for tid (thread ID), –this doesn't always work! Thread attributes can be set using attr, –including detached state and scheduling policy. –You can specify NULL and get the system defaults. Threads Programming 62

Thread IDs Each thread has a unique ID, a thread can find out it's ID by calling pthread_self(). Thread IDs are of type pthread_t which is usually an unsigned int. When debugging, it's often useful to do something like this: printf("Thread %u:\n",pthread_self()); Threads Programming 63

Thread Arguments When func() is called the value arg specified in the call to pthread_create() is passed as a parameter – func can have only 1 parameter, and it can't be larger than the size of a void * Complex parameters can be passed by using structures – The structure can't be a local variable of the function calling pthread_create !! threads have different stacks! Threads Programming 64

Thread args example struct { int x,y } 2ints; void *blah( void *arg) { struct 2ints *foo = (struct 2ints *) arg; printf("%u sum of %d and %d is %d\n", pthread_self(), foo->x, foo->y, foo->x+foo->y); return(NULL); } Threads Programming 65

Thread Lifespan Once a thread is created, –it starts executing function func() specified in the call to pthread_create() If func() returns, thread is terminated A thread can also be terminated by calling pthread_exit() If main() returns or any thread calls exit() –all threads are terminated. Threads Programming 66

Detached State Each thread can be either joinable or detached. Detached: on termination all thread resources are released by the OS. A detached thread cannot be joined. No way to get at the return value of the thread. – a pointer to something: void * Threads Programming 67

Joinable Thread Joinable: on thread termination thread ID and exit status are saved by the OS One thread can "join" another by calling pthread_join –which waits (blocks) until a specified thread exits int pthread_join( pthread_t tid, void **status); Threads Programming 68

Shared Global Variables int counter=0; void *pancake(void *arg) { counter++; printf("Thread %u is number %d\n", pthread_self(), counter); } main() { int i; pthread_t tid; for (i=0;i<10;i++) pthread_create(&tid,NULL,pancake,NULL); } Threads Programming 69

DANGER! DANGER! DANGER! Sharing global variables is dangerous –two threads may attempt to modify the same variable at the same time. Just because you don't see a problem when running your code doesn't mean it can't and won't happen!!!! Threads Programming 70

Avoiding Problems pthreads includes support for Mutual Exclusion primitives that can be used to protect against this problem. The general idea is to lock something before accessing global variables and to unlock as soon as you are done. Shared socket descriptors should be treated as global variables!!! Netprog: Threads Programming 71

pthread_mutex A global variable of type pthread_mutex_t is required: pthread_mutex_t counter_mtx= PTHREAD_MUTEX_INITIALIZER; Initialization to PTHREAD_MUTEX_INITIALIZER is required for a static variable! Threads Programming 72

Threads Programming 73 Locking and Unlocking To lock use: pthread_mutex_lock(pthread_mutex_t &); To unlock use: pthread_mutex_unlock(pthread_mutex_t &); Both functions are blocking!

Example Problem A server creates a thread for each client. No more than n threads (and therefore n clients) can be active at once. How can we have the main thread know when a child thread has terminated and it can now service a new client? Threads Programming 74

pthread_join() doesn’t help pthread_join requires that we specify a thread id. – is sort of like wait() We can wait for a specific thread, – but we can't wait for "the next thread to exit" Threads Programming 75

Use a global variable When each thread starts up: –acquires a lock on the variable (using a mutex) –increments the variable –releases the lock. When each thread shuts down: –acquires a lock on the variable (using a mutex) –decrements the variable –releases the lock. Threads Programming 76

What about the main loop? active_threads=0; // start up n threads on first n clients // make sure they are all running while (1) { // have to lock/relase active_threads if (active_threads < n) // start up thread for next client busy_waiting(is_bad); } Threads Programming 77

Condition Variables pthreads support condition variables, –which allow one thread to wait (sleep) for an event generated by any other thread. This allows us to avoid the busy waiting problem. pthread_cond_t foo = PTHREAD_COND_INITIALIZER; Threads Programming 78

Condition Variables (cont.) A condition variable is always used with mutex. pthread_cond_wait(pthread_cond_t *cptr, pthread_mutex_t *mptr); pthread_cond_signal(pthread_cond_t *cptr); Threads Programming 79 don’t let the word signal confuse you - this has nothing to do with Unix signals

Revised strategy Each thread decrements active_threads when terminating and calls pthread_cond_signal to wake up the main loop The main thread increments active_threads when each thread is started and waits for changes by calling pthread_cond_wait All changes to active_threads must be inside the lock and release of a mutex If two threads are ready to exit at (nearly) the same time –the second must wait until the main loop recognizes the first We don’t lose any of the condition signals Threads Programming 80

Global Variables // global variable the number of active // threads (clients) int active_threads=0; // mutex used to lock active_threads pthread_mutex_t at_mutex = PTHREAD_MUTEX_INITIALIZER; // condition var. used to signal changes pthread_cond_t at_cond = PTHREAD_COND_INITIALIZER; Threads Programming 81

Child Thread Code void *cld_func(void *arg) {... // handle the client... pthread_mutex_lock(&at_mutex); active_threads--; pthread_cond_signal(&at_cond); pthread_mutex_unlock(&at_mutex); return(); } Threads Programming 82

Main thread // no need to lock yet active_threads=0; while (1) { pthread_mutex_lock(&at_mutex); while (active_threads < n ) { active_threads++; pthread_start(…) } pthread_cond_wait( &at_cond, &at_mutex); pthread_mutex_unlock(&at_mutex); } IMPORTANT! Must happen while the mutex lock is held. Threads Programming 83

Other pthread functions Sometimes a function needs to have thread specific data –eg, a function that uses a static local Functions that support thread specific data: pthread_key_create() pthread_once() pthread_getspecific() pthread_setspecific() Threads Programming 84

Thread Safe library functions You have to be careful with libraries. If a function uses any static variables (or global memory) it’s not safe to use with threads! The book has a list of the Posix thread-safe functions… Threads Programming 85

Thread Summary Threads are awesome, but dangerous. You have to pay attention to details or it's easy to end up with code that is incorrect –doesn't always work, or hangs in deadlock Posix threads provides support for –mutual exclusion, –condition variables and –thread-specific data. Threads Programming 86