The OMNI Thread Abstraction

Similar documents
CS 162 Operating Systems and Systems Programming Professor: Anthony D. Joseph Spring Lecture 8: Semaphores, Monitors, & Condition Variables

Orbix TS Thread Library Reference

TS Thread Library Reference. Version 6.2, December 2004

UNIT III- INTER PROCESS COMMUNICATIONS Part A

Operating Systems, Assignment 2 Threads and Synchronization

Concurrency, Thread. Dongkun Shin, SKKU

Introduction to PThreads and Basic Synchronization

Chenyu Zheng. CSCI 5828 Spring 2010 Prof. Kenneth M. Anderson University of Colorado at Boulder

ECE 574 Cluster Computing Lecture 8

CSE 451 Midterm 1. Name:

The University of Texas at Arlington

The University of Texas at Arlington

CS510 Advanced Topics in Concurrency. Jonathan Walpole

Real Time Operating Systems and Middleware

Functions (API) Setup Functions

Lecture 8: September 30

Thread. Disclaimer: some slides are adopted from the book authors slides with permission 1

Locks. Dongkun Shin, SKKU

Systèmes d Exploitation Avancés

Operating Systems CMPSCI 377 Spring Mark Corner University of Massachusetts Amherst

Outline. Threads. Single and Multithreaded Processes. Benefits of Threads. Eike Ritter 1. Modified: October 16, 2012

Synchronising Threads

Programming with MPI

Synchronization I. To do

Operating System Architecture. CS3026 Operating Systems Lecture 03

Chapter 4: Threads. Overview Multithreading Models Thread Libraries Threading Issues Operating System Examples Windows XP Threads Linux Threads

CS 326: Operating Systems. Process Execution. Lecture 5

Questions from last time

Locks and semaphores. Johan Montelius KTH

Operating Systems. VI. Threads. Eurecom. Processes and Threads Multithreading Models

CS604 - Operating System Solved Subjective Midterm Papers For Midterm Exam Preparation

Concurrent Server Design Multiple- vs. Single-Thread

Outline. CS4254 Computer Network Architecture and Programming. Introduction 2/4. Introduction 1/4. Dr. Ayman A. Abdel-Hamid.

Systems Programming/ C and UNIX

CS 5523 Operating Systems: Midterm II - reivew Instructor: Dr. Tongping Liu Department Computer Science The University of Texas at San Antonio

Programming Assignment #4 Writing a simple parallel port device driver

Multiprocessors 2007/2008

Operating Systems (234123) Spring (Homework 3 Wet) Homework 3 Wet

PROCESS SYNCHRONIZATION

Project 2 : User Level Thread Library Operating Systems September 19, 2003

CS533 Concepts of Operating Systems. Jonathan Walpole

Synchronization I. Today. Next time. Race condition, critical regions and locks. Condition variables, semaphores and Monitors

Synchronization I. Today. Next time. Monitors. ! Race condition, critical regions and locks. ! Condition variables, semaphores and

recap, what s the problem Locks and semaphores Total Store Order Peterson s algorithm Johan Montelius 0 0 a = 1 b = 1 read b read a

Threaded Programming. Lecture 9: Alternatives to OpenMP

Concurrency: a crash course

SmartHeap for Multi-Core

POSIX / System Programming

Threads. Thread Concept Multithreading Models User & Kernel Threads Pthreads Threads in Solaris, Linux, Windows. 2/13/11 CSE325 - Threads 1

CS 550 Operating Systems Spring Concurrency Semaphores, Condition Variables, Producer Consumer Problem

ENGR 3950U / CSCI 3020U UOIT, Fall 2012 Quiz on Process Synchronization SOLUTIONS

CS 333 Introduction to Operating Systems. Class 3 Threads & Concurrency. Jonathan Walpole Computer Science Portland State University

POSIX Threads. Paolo Burgio

Programming with MPI

Reminder from last time

Review: Processes. A process is an instance of a running program. POSIX Thread APIs:

Threads and Synchronization. Kevin Webb Swarthmore College February 15, 2018

Preview. What are Pthreads? The Thread ID. The Thread ID. The thread Creation. The thread Creation 10/25/2017

CS 333 Introduction to Operating Systems. Class 3 Threads & Concurrency. Jonathan Walpole Computer Science Portland State University

Background. The Critical-Section Problem Synchronisation Hardware Inefficient Spinning Semaphores Semaphore Examples Scheduling.

Che-Wei Chang Department of Computer Science and Information Engineering, Chang Gung University

pthread Tutorial August 23, Creating and Destroying Threads Creating Threads Returning Results from Threads...

CS 105, Spring 2015 Ring Buffer

CISC2200 Threads Spring 2015

Synchronization and Semaphores. Copyright : University of Illinois CS 241 Staff 1

Locks and semaphores. Johan Montelius KTH

Semaphore. Originally called P() and V() wait (S) { while S <= 0 ; // no-op S--; } signal (S) { S++; }

Synchronization for Concurrent Tasks

SYNCHRONIZATION M O D E R N O P E R A T I N G S Y S T E M S R E A D 2. 3 E X C E P T A N D S P R I N G 2018

Recap: Thread. What is it? What does it need (thread private)? What for? How to implement? Independent flow of control. Stack

For 100% Result Oriented IGNOU Coaching and Project Training Call CPD: ,

Comparison of soft real-time CPU scheduling in Linux kernel 2.6 series with Solaris 10

2 Threads vs. Processes

Contents. Chapter 1 Overview of the JavaScript C Engine...1. Chapter 2 JavaScript API Reference...23

CS 153 Lab6. Kishore Kumar Pusukuri

1 Process Coordination

CS 167 Final Exam Solutions

Any of the descriptors in the set {1, 4} have an exception condition pending

Chapter 4: Threads. Operating System Concepts with Java 8 th Edition

Summary Semaphores. Passing the Baton any await statement. Synchronisation code not linked to the data

Process Coordination and Shared Data

ECE 598 Advanced Operating Systems Lecture 23

Concurrency: Deadlock and Starvation

Page 1. Goals for Today" Atomic Read-Modify-Write instructions" Examples of Read-Modify-Write "

CS 385 Operating Systems Fall 2011 Homework Assignment 5 Process Synchronization and Communications

W4118 Operating Systems. Instructor: Junfeng Yang

CS 162 Operating Systems and Systems Programming Professor: Anthony D. Joseph Spring 2004

Lecture 13 Condition Variables

PThreads in a Nutshell

TCSS 422: OPERATING SYSTEMS

Overview of Unix / Linux operating systems

OPERATING SYSTEMS ASSIGNMENT 2 SIGNALS, USER LEVEL THREADS AND SYNCHRONIZATION

real time operating systems course

Chap. 6 Part 1. CIS*3090 Fall Fall 2016 CIS*3090 Parallel Programming 1

Dealing with Issues for Interprocess Communication

Deadlock. Concurrency: Deadlock and Starvation. Reusable Resources

Interprocess Communication By: Kaushik Vaghani

연세대학교전기전자공학과프로세서연구실박사과정김재억.

Shared-Memory Parallelization of an Interval Equations Systems Solver Comparison of Tools

The Dining Philosophers Problem CMSC 330: Organization of Programming Languages

Transcription:

The OMNI Thread Abstraction Tristan Richardson AT&T Laboratories Cambridge Revised November 2001 1 Introduction The OMNI thread abstraction is designed to provide a common set of thread operations for use in programs written in C++. Programs written using the abstraction should be much easier to port between different architectures with different underlying threads primitives. The programming interface is designed to be similar to the C language interface to POSIX threads (IEEE draft standard 1003.1c previously 1003.4a, often known as pthreads [POSIX94]). Much of the abstraction consists of simple C++ object wrappers around pthread calls. However for some features such as thread-specific data, a better interface can be offered because of the use of C++. Some of the more complex features of pthreads are not supported because of the difficulty of ensuring the same features can be offered on top of other thread systems. Such features include thread cancellation and complex scheduling control (though simple thread priorities are supported). The abstraction layer is currently implemented for the following architectures / thread systems: Solaris 2.x using pthreads draft 10 Solaris 2.x using solaris threads (but pthreads version is now standard) Alpha OSF1 using pthreads draft 4 Windows NT using NT threads Linux 2.x using Linuxthread 0.5 (which is based on pthreads draft 10) Linux 2.x using MIT pthreads (which is based on draft 8) ATMos using pthreads draft 6 (but not Virata ATMos) 1

2 2 SYNCHRONISATION OBJECTS See the omnithread.h header file for full details of the API. The descriptions below assume you have some previous knowledge of threads, mutexes, condition variables and semaphores. Also refer to other documentation ([Birrell89], [POSIX94]) for further explanation of these ideas (particularly condition variables, the use of which may not be particularly intuitive when first encountered). 2 Synchronisation objects Synchronisation objects are used to synchronise threads within the same process. There is no inter-process synchronisation provided. The synchronisation objects provided are mutexes, condition variables and counting semaphores. 2.1 Mutex An object of type omni_mutex is used for mutual exclusion. It provides two operations, lock() and unlock(). The alternative names acquire() and release() can be used if preferred. Behaviour is undefined when a thread attempts to lock the same mutex again or when a mutex is locked by one thread and unlocked by a different thread. 2.2 Condition Variable A condition variable is represented by an omni_condition and is used for signalling between threads. A call to wait() causes a thread to wait on the condition variable. A call to signal() wakes up at least one thread if any are waiting. A call to broadcast() wakes up all threads waiting on the condition variable. When constructed, a pointer to an omni_mutex must be given. A condition variable wait() has an implicit mutex unlock() and lock() around it. The link between condition variable and mutex lasts for the lifetime of the condition variable (unlike pthreads where the link is only for the duration of the wait). The same mutex may be used with several condition variables. A wait with a timeout can be achieved by calling timed_wait(). This is given an absolute time to wait until. The routine omni_thread::get_time() can be used to turn a relative time into an absolute time. timed_wait() returns true if the condition was signalled, false if the time expired before the condition variable was signalled. 2.3 Counting semaphores An omni_semaphore is a counting semaphore. When created it is given an initial unsigned integer value. When wait() is called, the value is decremented if nonzero. If the value is zero then the thread blocks instead. When post() is called, if any threads are blocked in wait(), exactly one thread is woken. If no threads were blocked then the value of the semaphore is incremented.

3 If a thread calls try_wait(), then the thread won t block if the semaphore s value is 0, returning false instead. There is no way of querying the value of the semaphore. 3 Thread object A thread is represented by an omni_thread object. There are broadly two different ways in which it can be used. The first way is simply to create an omni_thread object, giving a particular function which the thread should execute. This is like the POSIX (or any other) C language interface. The second method of use is to create a new class which inherits from omni_ thread. In this case the thread will execute the run() member function of the new class. One advantage of this scheme is that thread-specific data can be implemented simply by having data members of the new class. When constructed a thread is in the "new" state and has not actually started. A call to start() causes the thread to begin executing. A static member function create() is provided to construct and start a thread in a single call. A thread exits by calling exit() or by returning from the thread function. Threads can be either detached or undetached. Detached threads are threads for which all state will be lost upon exit. Other threads cannot determine when a detached thread will disappear, and therefore should not attempt to access the thread object unless some explicit synchronisation with the detached thread guarantees that it still exists. Undetached threads are threads for which storage is not reclaimed until another thread waits for its termination by calling join(). An exit value can be passed from an undetached thread to the thread which joins it. Detached / undetached threads are distinguished on creation by the type of function they execute. Undetached threads execute a function which has a void* return type, whereas detached threads execute a function which has a void return type. Unfortunately C++ member functions are not allowed to be distinguished simply by their return type. Thus in the case of a derived class of omni_thread which needs an undetached thread, the member function executed by the thread is called run_undetached() rather than run(), and it is started by calling start_ undetached() instead of start(). The abstraction currently supports three priorities of thread, but no guarantee is made of how this will affect underlying thread scheduling. The three priorities are PRIORITY_LOW, PRIORITY_NORMAL and PRIORITY_HIGH. By default all threads run at PRIORITY_NORMAL. A different priority can be specified on thread creation, or while the thread is running using set_priority(). A thread s current priority is returned by priority(). Other functions provided are self() which returns the calling thread s omni_ thread object, yield() which requests that other threads be allowed to run,

4 5 THREADED I/O SHUTDOWN FOR UNIX id() which returns an integer id for the thread for use in debugging, state(), sleep() and get_time(). 4 Using OMNI threads in your program Obviously you need to include the omnithread.h header file in your source code, and link in the omnithread library with your executable. Because there is a single omnithread.h for all platforms, certain preprocessor defines must be given as compiler options. The easiest way to do this is to study the makefiles given in the examples provided with this distribution. If you are to include OMNI threads in your own development environment, these are the necessary preprocessor defines: Platform Sun Solaris 2.x x86 Linux 2.0 with linuxthreads 0.5 Digital Unix 3.2 Windows NT Preprocessor Defines -D sunos -D sparc -D OSVERSION =5 -DSVR4 -DUsePthread -D_REENTRANT -D linux -D i86 -D OSVERSION =2 -D_REENTRANT -D osf1 -D alpha -D OSVERSION =3 -D_REENTRANT -D NT -MD 5 Threaded I/O shutdown for Unix or, how one thread should tell another thread to shut down when it might be doing a blocking call on a socket. If you are using omniorb, you don t need to worry about all this, since omniorb does it for you. This section is only relevant if you are using omnithread in your own socket-based programming. It is also seriously out of date. Unfortunately there doesn t seem to be a standard way of doing this which works across all Unix systems. I have investigated the behaviour of Solaris 2.5 and Digital Unix 3.2. On Digital Unix everything is fine, as the obvious method using shutdown() seems to work OK. Unfortunately on Solaris shutdown can only be used on a connected socket, so we need devious means to get around this limitation. The details are summarised below: 5.1 read() Thread A is in a loop, doing read(sock), processing the data, then going back into the read. Thread B comes along and wants to shut it down it can t cancel thread A since (i) working out how to clean up according to where A is in its loop is a nightmare, and (ii) this isn t available in omnithread anyway. On Solaris 2.5 and Digital Unix 3.2 the following strategy works:

5.2 accept() 5 At this point thread A is either blocked inside read(sock), or is elsewhere in the loop. If the former then read will return 0, indicating that the socket is closed. If the latter then eventually thread A will call read(sock) and then this will return 0. Thread A should close(sock), do any other tidying up, and exit. If there is another point in the loop that thread A can block then obviously thread B needs to be aware of this and be able to wake it up in the appropriate way from that point. 5.2 accept() Again thread A is in a loop, this time doing an accept on listensock, dealing with a new connection and going back into accept. Thread B wants to cancel it. On Digital Unix 3.2 the strategy is identical to that for read: Thread B does shutdown(listensock,2). Wherever thread A is in the loop, eventually it will return ECONNABORTED from the accept call. It should close(listensock), tidy up as necessary and exit. On Solaris 2.5 thread B can t do shutdown(listensock,2) this returns ENOTCONN. Instead the following strategy can be used: First thread B sets some sort of "shutdown flag" associated with listensock. Then it does getsockaddr(listensock) to find out which port listensock is on (or knows already), sets up a socket dummysock, does connect(dummysock, this host, port) and finally does close(dummysock). Wherever thread A is in the loop, eventually it will call accept(listensock). This will return successfully with a new socket, say connsock. Thread A then checks to see if the "shutdown flag" is set. If not, then it s a normal connection. If it is set, then thread A closes listensock and connsock, tidies up and exits. 5.3 write() Thread A may be blocked in write, or about to go in to a potentially-blocking write. Thread B wants to shut it down. On Solaris 2.5: If thread A is already in write(sock) then it will return with ENXIO. If thread A calls write after thread B calls shutdown this will return EIO. On Digital Unix 3.2: If thread A is already in write(sock) then it will return the number of bytes written before it became blocked. A subsequent call to write will then generate SIGPIPE (or EPIPE will be returned if SIGPIPE is ignored by the thread).

6 REFERENCES 5.4 connect() Thread A may be blocked in connect, or about to go in to a potentially-blocking connect. Thread B wants to shut it down. On Digital Unix 3.2: If thread A is already in connect(sock) then it will return a successful connection. Subsequent reading or writing will show that the socket has been shut down (i.e. read returns 0, write generates SIGPIPE or returns EPIPE). If thread A calls connect after thread B calls shutdown this will return EINVAL. On Solaris 2.5: There is no way to wake up a thread which is blocked in connect. Instead Solaris forces us through a ridiculous procedure whichever way we try it. One way is this: First thread A creates a pipe in addition to the socket. Instead of shutting down the socket, thread B simply writes a byte to the pipe. Thread A meanwhile sets the socket to non-blocking mode using fcntl(sock, F_SETFL, O_NONBLOCK). Then it calls connect on the socket this will return EINPROGRESS. Then it must call select(), waiting for either sock to become writable or for the pipe to become readable. If select returns that just sock is writable then the connection has succeeded. It then needs to set the socket back to blocking mode using fcntl(sock, F_SETFL, 0). If instead select returns that the pipe is readable, thread A closes the socket, tidies up and exits. An alternative method is similar but to use polling instead of the pipe. Thread B justs sets a flag and thread A calls select with a timeout, periodically waking up to see if the flag has been set. References [POSIX94] Portable Operating System Interface (POSIX) Threads Extension, P1003.1c Draft 10, IEEE, September 1994. [Birrell89] An Introduction to Programming with Threads, Research Report 35, DEC Systems Research Center, Palo Alto, CA, January 1989.