Threads Threads are lightweight processes In a context switch, they change the contents of the CPU registers but do not change memory Threads can simplify.

Slides:



Advertisements
Similar presentations
Copyright ©: Nahrstedt, Angrave, Abdelzaher1 pThreads.
Advertisements

Threads. Readings r Silberschatz et al : Chapter 4.
1 Threads. 2 Real Life Example?  Process  “system programming” course  Different from “internet engineering”  Thread  homework, Reading, Self-assessment.
Silberschatz, Galvin and Gagne ©2009 Operating System Concepts – 8 th Edition, Lecture 6: Threads Chapter 4.
Threads By Dr. Yingwu Zhu. Review Multithreading Models Many-to-one One-to-one Many-to-many.
Threads By Dr. Yingwu Zhu.
Computer Architecture II 1 Computer architecture II Programming: POSIX Threads OpenMP.
Threads Threads are lightweight processes In a context switch, they change the contents of the CPU registers but do not change memory Threads can simplify.
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.
Threads Threads are lightweight processes
Unix Threads operating systems. User Thread Packages pthread package mach c-threads Sun Solaris3 UI threads Kernel Threads Windows NT, XP operating systems.
Project 2 Hints. pthread_create SYNOPSIS #include int pthread_create(pthread_t *tid, const pthread_attr_t *attr, void *(*start_routine)(void *), void.
Threads© Dr. Ayman Abdel-Hamid, CS4254 Spring CS4254 Computer Network Architecture and Programming Dr. Ayman A. Abdel-Hamid Computer Science Department.
Threads Threads are lightweight processes In a context switch, they change the contents of the CPU registers but do not change memory Threads can simplify.
Chapter 4: Threads Adapted to COP4610 by Robert van Engelen.
Thread. A basic unit of CPU utilization. It comprises a thread ID, a program counter, a register set, and a stack. It is a single sequential flow of control.
Introduction to Pthreads. Pthreads Pthreads is a POSIX standard for describing a thread model, it specifies the API and the semantics of the calls. Model.
1 Threads Chapter 11 from the book: Inter-process Communications in Linux: The Nooks & Crannies by John Shapley Gray Publisher: Prentice Hall Pub Date:
10/16/ Realizing Concurrency using the thread model B. Ramamurthy.
Today’s topic Pthread Some materials and figures are obtained from the POSIX threads Programming tutorial at
B. RAMAMURTHY 10/24/ Realizing Concurrency using the thread model.
Operating Systems CMPSC 473 Multi-threading models Tutorial on pthreads Lecture 10: September Instructor: Bhuvan Urgaonkar.
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.
Chapter 12 POSIX Threads Source: Robbins and Robbins, UNIX Systems Programming, Prentice Hall, 2003.
1 Threads Chapter 11 from the book: Inter-process Communications in Linux: The Nooks & Crannies by John Shapley Gray Publisher: Prentice Hall Pub Date:
Copyright ©: University of Illinois CS 241 Staff1 Threads Systems Concepts.
1 Threads. 2 Processes versus Threads 3 Why Threads? Processes do not share resources very well Why? Process context switching cost is very high Why?
Source: Operating System Concepts by Silberschatz, Galvin and Gagne.
CS333 Intro to Operating Systems Jonathan Walpole.
Threads CSCE Thread Motivation Processes are expensive to create. Context switch between processes is expensive Communication between processes.
Threads Chapter 26. Threads Light-weight processes Each process can have multiple threads of concurrent control. What’s wrong with processes? fork() is.
1 Pthread Programming CIS450 Winter 2003 Professor Jinhua Guo.
Pthreads.
Silberschatz, Galvin and Gagne  2002 Modified for CSCI 399, Royden, Operating System Concepts Operating Systems Lecture 14 Threads 2 Read Ch.
12/22/ Thread Model for Realizing Concurrency B. Ramamurthy.
© Janice Regan, CMPT 300, May CMPT 300 Introduction to Operating Systems Operating Systems Processes and Threads.
CS307 Operating Systems Threads Fan Wu Department of Computer Science and Engineering Shanghai Jiao Tong University Spring 2011.
Copyright ©: Nahrstedt, Angrave, Abdelzaher
Threads A thread is an alternative model of program execution
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:
B. RAMAMURTHY 5/10/2013 Amrita-UB-MSES Realizing Concurrency using the thread model.
7/9/ Realizing Concurrency using Posix Threads (pthreads) B. Ramamurthy.
CMSC 421 Spring 2004 Section 0202 Part II: Process Management Chapter 5 Threads.
Tutorial 4. In this tutorial session we’ll see Threads.
A thread is a basic unit of CPU utilization within a process Each thread has its own – thread ID – program counter – register set – stack It shares the.
Realizing Concurrency using the thread model
Threads Some of these slides were originally made by Dr. Roger deBry. They include text, figures, and information from this class’s textbook, Operating.
Realizing Concurrency using the thread model
Threads Threads.
Copyright ©: Nahrstedt, Angrave, Abdelzaher
CS399 New Beginnings Jonathan Walpole.
Thread Programming.
Chapter 4: Threads.
Realizing Concurrency using Posix Threads (pthreads)
Operating Systems Lecture 13.
Realizing Concurrency using the thread model
Thread Programming.
Realizing Concurrency using the thread model
CS510 Operating System Foundations
Operating System Concepts
Programming with Shared Memory
Jonathan Walpole Computer Science Portland State University
Realizing Concurrency using the thread model
Realizing Concurrency using Posix Threads (pthreads)
Realizing Concurrency using the thread model
Programming with Shared Memory
Realizing Concurrency using Posix Threads (pthreads)
Concurrency and Threading: Introduction
Outline Chapter 3: Processes Chapter 4: Threads So far - Next -
Presentation transcript:

Threads Threads are lightweight processes In a context switch, they change the contents of the CPU registers but do not change memory Threads can simplify the programming of problems such as monitoring inputs from multiple file descriptors They also provide a capability to overlap I/O with processing Typical thread packages contain a runtime system to manage threads in a transparent way A thread package contains calls for thread creation and destruction, mutual exclusion, and condition variables POSIX.THR and Sun Solaris 2 standard libraries have such calls

Methods to Monitor Multiple File Descriptors Have a separate process monitor each file descriptor Use the select command Use the poll command Use POSIX asynchronous I/O Create a thread to monitor each file descriptor

Without Threads Calling Process process_fd(); Called Function process_fd(void) { } Thread of execution

With Threads Creating Process pthread_create(); Created Thread process_fd(void) { } Thread Creation Thread of execution

processfd.c #include #include "restart.h" #define BUFSIZE 1024 void docommand(char *cmd, int cmdsize); void *processfd(void *arg) { /* process commands read from file descriptor */ char buf[BUFSIZE]; int fd; ssize_t nbytes; fd = *((int *)(arg)); for ( ; ; ) { if ((nbytes = r_read(fd, buf, BUFSIZE)) <= 0) break; docommand(buf, nbytes); } return NULL; }

processid.c Analysis Processid.c monitors only one file descriptor for an input The input is a command for execution

monitorfd.c - top #include void *processfd(void *arg); void monitorfd(int fd[], int numfds) { /* create threads to monitor fds */ int error, i; pthread_t *tid; if ((tid = (pthread_t *)calloc(numfds, sizeof(pthread_t))) == NULL) { perror("Failed to allocate space for thread IDs"); return; }

monitorfd.c for (i = 0; i < numfds; i++) /* create a thread for each file descriptor */ if (error = pthread_create(tid + i, NULL, processfd, (fd + i))) { fprintf(stderr, "Failed to create thread %d: %s\n", i, strerror(error)); tid[i] = pthread_self(); } for (i = 0; i < numfds; i++) { if (pthread_equal(pthread_self(), tid[i])) continue; if (error = pthread_join(tid[i], NULL)) fprintf(stderr, "Failed to join thread %d: %s\n", i, strerror(error)); } free(tid); return; }

POSIX vs Solaris 2 (1) Most thread functions return 0 if successful and nonzero error code if unsuccessful pthread_create (thr_create) – Creates a thread pthread_exit (thr_exit) – Causes the calling thread to terminate without causing the entire process to exit pthread_kill (thr_kil) – sends a signal to a specified thread pthread_join (thr_join) – causes the calling thread to wait for the specified thread to exit pthread_self (thr_self) – returns the caller’s identity

POSIX vs Solaris 2 (2) – Old Book DescriptionPOSIXSolaris 2 Thread Managementpthread_create pthread_exit pthread_kill pthread_join pthread_self thr_create thr_exit thr_kill thr_join thr_self Mutual exclusionpthread_mutex_init pthread_mutex_destroy pthread_mutex_lock pthread_mutex_trylock pthread_mutex_unlock mutex_init mutex_destroy mutex_lock mutex_trylock mutex_unlock Condition variablespthread_cond_init pthread _cond_destroy pthread _cond_wait pthread _cond_timewait pthread _cond_signal pthread _cond_broadcast cond_init cond_destroy cond_wait cond_timewait cond_signal cond_broadcast

Thread Management Functions – New Book POSIX functiondescription pthread_cancelterminate another thread pthread_createcreate a thread pthread_detachset thread to release resources pthread_equaltest two thread ID’s for equality pthread_killsend a signal to a thread pthread_joinwait for a thread pthread_selffind out own thread ID

POSIX.THR Threads POSIX:THR uses attribute objects to represent thread properties Properties such as stack size or scheduling policy are set for a thread attribute object Several threads can be associated with the same attribute object If a property of an object changes, the change is reflected in all threads associated with the object POSIX:THR threads offer a more robust method of thread cancellation and termination (than Solaris)

Sun Solaris 2 Threads Solaris threads explicitly set properties of threads and other primitives Therefore, some calls have long lists of parameters for setting properties Solaris offers more control over how threads are mapped to processor resources (than POSIX)

Thread Management A thread has an ID, stack, execution priority, and starting address for execution (and perhaps scheduling and usage information) POSIX threads are referenced by an ID of type pthread_t A thread determines its ID by calling pthread_self Threads for a process share the entire address space for that process Threads are dynamic if they can be created at any time during execution POSIX:THR creates threads dynamically with pthread_create (creates thread and places it in the ready queue)

pthread_create SYNOPSIS #include int pthread_create(pthread_t *tid, const pthread_attr_t *attr, void *(*start_routine)(void *), void *arg); POSIX:THR tid points to thread ID attr points to attributes of thread (NULL implies default attributes) start routine points to function thread calls when it begins execution start routine returns a pointer to void which is treated as exit status by pthread_join

pthread_exit/pthread_join SYNOPSIS #include void pthread_exit(void *value_ptr); int pthread_join(pthread_t thread, void **value_ptr); POSIX.THR pthread_exit terminates the calling thread The value_ptr parameter is available to a successful pthread_join However, the pthread_exit value_ptr parameter points to data that exists after the thread exits, so it cannot be allocated as an automatic local variable

#include #include #include #include #include #include void main(void) { pthread_t copy_tid; int myarg[2]; int error; void *copy_file(void *arg); if ((myarg[0] = open("my.in", O_RDONLY)) == -1) perror("Could not open my.in"); else if ((myarg[1] = open("my.out", O_WRONLY | O_CREAT, S_IRUSR | S_IWUSR)) == -1) perror("Could not open my.out"); else if (error=pthread_create(&copy_tid, NULL, copy_file, (void *)myarg)) fprintf(stderr,"Thread creation was not successful: %s\n", strerror(error)); } PTHREAD Example

Thread – Example 2 (cont) copy_tid holds the ID of the created thread copy_file is the name of the function the thread executes myarg is a pointer to the parameter value to be passed to the thread function (contains file descriptors for my.in and my.out)

Thread – Example 3 (1) /* Program 9.9 */ #include #include #include #include #include #include #include #include #define MAXNUMCOPIERS 10 #define MAXNAMESIZE 80 void *copy_file(void *arg);

Thread – Example 3 (2) void main(int argc, char *argv[]) { pthread_t copiertid[MAXNUMCOPIERS]; int fd[MAXNUMCOPIERS][2]; char filename[MAXNAMESIZE]; int numcopiers; int total_bytes_copied=0; int *bytes_copied_p; int error; int i; if (argc != 4) { fprintf(stderr, "Usage: %s infile outfile copiers\n", argv[0]); exit(1); } numcopiers = atoi(argv[3]); if (numcopiers MAXNUMCOPIERS) { fprintf(stderr, "%d invalid number of copiers\n", numcopiers); exit(1); }

Thread – Example 3 (3) for (i = 0; i < numcopiers; i++) { sprintf(filename, "%s.%d", argv[1], i); if ((fd[i][0] = open(filename, O_RDONLY)) < 0) { fprintf(stderr, "Unable to open copy source file %s: %s\n", filename, strerror(errno)); continue; } sprintf(filename, "%s.%d", argv[2], i); if ((fd[i][1]= open(filename, O_WRONLY | O_CREAT, S_IRUSR | S_IWUSR)) < 0) { fprintf(stderr, "Unable to create copy destination file %s: %s\n", filename, strerror(errno)); continue; } if (error=pthread_create(&copiertid[i], NULL, copy_file, (void *)fd[i])) fprintf(stderr, "Could not create thread %d: %s\n", i,strerror(error)); } /* wait for copy to complete */

Thread – Example 3 (4) for (i = 0; i < numcopiers; i++) { if (error=pthread_join(copiertid[i], (void **)&(bytes_copied_p))) fprintf(stderr, "No thread %d to join\n",i); else { printf("Thread %d copied %d bytes from %s.%d to %s.%d\n", i, *bytes_copied_p, argv[1], i, argv[2], i); total_bytes_copied += *bytes_copied_p; } } printf("Total bytes copied = %d\n", total_bytes_copied); exit(0); }

copy_file – Example 3 (top) /* Program 9.8 */ #include #include #include #include #include #define BUFFERSIZE 100 void *copy_file(void *arg) { int infile; int outfile; int bytes_read = 0; int bytes_written = 0; int *bytes_copied_p; char buffer[BUFFERSIZE]; char *bufp;

copy_file – Example 3 (middle) /* open file descriptors for source and destination files */ infile = *((int *)(arg)); outfile = *((int *)(arg) + 1); if ((bytes_copied_p = (int *)malloc(sizeof(int))) == NULL) pthread_exit(NULL); *bytes_copied_p = 0; for ( ; ; ) { bytes_read = read(infile, buffer, BUFFERSIZE); if ((bytes_read == 0) || ((bytes_read 0) { bytes_written = write(outfile, bufp, bytes_read); if ((bytes_written < 0) && (errno != EINTR)) break;

copy_file – Example 3 (bottom) else if (bytes_written < 0) continue; *bytes_copied_p += bytes_written; bytes_read -= bytes_written; bufp += bytes_written; } if (bytes_written == -1) break; } close(infile); close(outfile); pthread_exit(bytes_copied_p); } What if malloc fails? – On pthread_join, bytes_copied_p is NULL and program crashes when it tries to dereference pointer (check for NULL pointer) What if errno is global? macro?

Bad Copier – Example 4 (1) /* Program 9.10 */ #include #include #include #include #include #include #include #include void *copy_file(void *arg); #define MAXNUMCOPIERS 10 #define MAXNAMESIZE 80

Bad Copier – Example 4 (2) void main(int argc, char *argv[]) { pthread_t copiertid[MAXNUMCOPIERS]; int fd[2]; char filename[MAXNAMESIZE]; int numcopiers; int total_bytes_copied=0; int *bytes_copied_p; int error; int i; if (argc != 4) { fprintf(stderr, "Usage: %s infile_name outfile_name copiers\n", argv[0]); exit(1); } numcopiers = atoi(argv[3]); if (numcopiers MAXNUMCOPIERS) { fprintf(stderr, "%d invalid number of copiers\n", numcopiers); exit(1); }

Bad Copier – Example 4 (3) for (i = 0; i < numcopiers; i++) { sprintf(filename, "%s.%d", argv[1], i); if ((fd[0] = open(filename, O_RDONLY)) < 0) { fprintf(stderr, "Unable to open copy source file %s: %s\n", filename, strerror(errno)); continue; } sprintf(filename, "%s.%d", argv[2], i); if ((fd[1] = open(filename, O_WRONLY | O_CREAT, S_IRUSR | S_IWUSR)) < 0) { fprintf(stderr, "Unable to create copy destination file %s: %s\n", filename, strerror(errno)); continue; } if (error=pthread_create(&copiertid[i], NULL, copy_file, (void *)fd)) fprintf(stderr, "Could not create thread %d: %s\n", i, strerror(error)); } /* wait for copy to complete */

Bad Copier – Example 4 (4) for (i = 0; i < numcopiers; i++) { if (error=pthread_join(copiertid[i], (void **)&(bytes_copied_p))) fprintf(stderr, "No thread %d to join: %s\n", i, strerror(error)); else { printf("Thread %d copied %d bytes from %s.%d to %s.%d\n", i, *bytes_copied_p, argv[1], i, argv[2], i); total_bytes_copied += *bytes_copied_p; } } printf("Total bytes copied = %d\n", total_bytes_copied); exit(0); } A different pair of file descriptors is opened for each thread, but the fd array is reused for each thread – If a sleep(5) is placed after the pthread_create, threads will probably be able to complete before a conflict occurs

User-Level Threads (1) Run on top of the existing operating system Compete among themselves for the resources allocated to a process Threads are scheduled by a run-time thread system that is part of the process code Each library/system call is enclosed by a “jacket” – jacket code calls the runtime system read and sleep could be a problem because they cause the process to block – the potentially blocking code is replaced in the jacket by non-blocking code If the code does not block, do the call right away – if the code does block, add it to a list to do later and pick another thread to run User-level threads have low overhead

User-Level Threads (2) Disadvantages –It relies on threads to allow the thread runtime system to regain control –CPU-bound thread rarely performs system/library calls preventing runtime system from regaining control to schedule other threads –Programmer must avoid lockout by explicitly forcing CPU-bound threads off CPU –Can share only resources allocated to encapsulating process – Therefore, they can only run on one processor (user-level threads are not good in a multi-processor system)

User-Level Threads (3) Runtime Mapping user-level thread kernel entity process

Kernel-Level Threads (1) The kernel schedules each thread Threads compete for resources just like processes do Scheduling threads is more expensive – almost as expensive as scheduling processes Kernel-level threads can take advantage of multiple processors

Kernel-Level Threads (2) kernel-level thread process

Hybrid Threads (1) Hybrid threads have the advantages of both user and kernel-level threads User writes program in terms of user-level threads and then specifies how many kernel-schedulable entities are associated with the process User-level threads are mapped into kernel-schedulable entities Sun Solaris calls the kernel-schedulable entities lightweight processes

Hybrid Threads (2) Runtime Mapping user-level thread kernel entity process

POSIX.1c Threads POSIX.1c supports hybrid threads Schedules threads and kernel entities –Threads are analogous to user-level threads –Kernel entities are scheduled by the kernel –Thread library decides how many kernel entities it needs and how to map them Thread Scheduling Contention Scope –Gives programmer control over how kernel entities are mapped to threads –PTHREAD_SCOPE_PROCESS contend for process resources –PTHREAD_SCOPE_SYSTEM contend for system resources

Solaris 2 Terminology Unbound Thread – User-level thread Bound Thread – Kernel-level thread (because it is bound to a lightweight process) fork() – Cost of creation of entire process synchronization – Two threads synchronizing with semaphores

Solaris 2.3 Service Times OperationMicroseconds Unbound thread create Bound thread create fork() Unbound thread synchronize Bound thread synchronize Between process synchronize

POSIX.1c Thread Attributes POSIX.1c takes an object-oriented approach to representation and assignment of thread properties Each POSIX.1c thread has an associated attribute object representing its properties An attribute object can be associated with multiple threads There are functions to create, configure, and destroy attribute objects When a property of an attribute object changes, all entities in the group have the new property Thread attribute objects are of type pthread_attr_t

POSIX.1c Attribute Objects PropertyFunction Initialization Stack Size Detach State Scope Inheritance Schedule Policy Schedule Parameters pthread_attr_init pthread_attr_destroy pthread_attr_setstacksize pthread_attr_setstackaddr pthread_attr_setdetachstate pthread_attr_getdetachstate pthread_attr_setscope pthread_attr_getscope pthread_setinheritsched pthread_getinheritsched pthread_attr_setschedpolicy pthread_attr_getschedpolicy pthread_attr_setschedparam pthread_attr_getschedparam

Attribute Object – Example … #include #define HIGHPRIORITY 10 pthread_attr_t my_tattr; pthread_t my_tid; struct sched_param param; int fd; if (pthread_attr_init(&my_tattr)) perror(“Could not initialize thrad attribute object”); else if (pthread_create(&my_tid,&my_tattr, do_it, (void *)&fd)) perror(“Could not create copier thread”); else if (pthread_attr_getschedparam(&my_tattr, &param)) perror(“Could not get scheduling parameters”); else { param.sched_priority = HIGHPRIORITY; if (pthread_attr_setschedparam(&my_tattr, & param)) perror (“could not set priority”); }