CPS 346 & 444/544 Lecture notes: Threads
Coverage: [OSCJ] Chapter 4 (pp. 133-165), and
[USP] Chapter
2
(pp. 21-23, 31-48) and Appendix A.5 (pp. 812-814)
Overview
(ref. [OSIDP] Fig. 4.1 on p. 162; image courtesy [OSIDP] webpage)
Introduction
A thread is
- an ADT within a process
- has its own stack, program counter value, register set, and state
- share process resources
(heavyweight) process vs. (lightweight) thread
We also have a thread control block (TCB).
Relationship between process
and thread states
(ref. [OSIDP] Fig. 4.7 on p. 170; image courtesy [OSIDP] webpage)
variables are either static (exist for the life of the process) or
automatic (allocated/deallocated on block entry/exit)
Declarations and definitions
- defining a variable entails allocating storage for it
(once per program)
- declaring a variable entails announcing its type so that
it can be used
- every definition is also a declaration (e.g., the definition
int x; is also a declaration)
- some declarations are not definitions (e.g., the
declaration extern int x; is not a definition)
extern modifier in C
/* x.c */
int x = 10;
#include<stdio.h>
/* main.c */
extern int x;
main() {
printf("%d\n", x);
}
Storage and linkage classes
- storage classes
- static storage: once allocated, persists throughout lifetime of program
(e.g., a global variable)
- automatic storage: allocated and deallocated on block/function entry and exit, resp. (e.g., a variable local to a function)
- linkage classes
- internal linkage: visible only within defining file
- external linkage: visible outside of defining file as well as within it
- statics and externals have 0 as a default value
- automatics have no default value
Storage class summary
| class | scope | life | storage |
init. arrays/structs | default value |
| automatic | block | block active | stack | yes | undefined |
| register (1) | block | block active | machine register | no | undefined (2) |
| external (3) | declaration to end-of-file | permanent | data area | yes | 0 |
| static external (4) | declaration to end-of-file | permanent | data area | yes | 0 |
| static internal | block | permanent | data area | yes | 0 |
notes:
- speed advantage
- for function arguments, value passed
- can be accessed from other files
- cannot be accessed from other files
(ref. [C])
static modifier in C
- can you write an object-oriented program in C?
- before a variable within a function
- if present, static storage
- if absent, automatic storage (default)
- before a variable outside of a function
- if present, internal linkage (like private in OO languages)
- if absent, external linkage (default)
- before a function
- if present, internal linkage (like private in OO languages)
- if absent, external linkage (default)
static modifier summary
(courtesy Robbins & Robbins' [USP] Chapter 2
webpage)
- variables:
| where declared |
static modifies |
static applied? |
storage class |
linkage class |
| inside a function |
storage class |
yes |
static |
none |
| inside a function |
storage class |
no |
automatic |
none |
| outside any function |
linkage class |
yes |
static |
internal |
| outside any function |
linkage class |
no |
static |
external |
(ref. [USP] Table A.3, p. 814; HTML table courtesy Robbins & Robbins'
[USP] Chapter
2
webpage)
- functions:
| static modifies |
static applied? |
linkage class |
| linkage class |
yes |
internal |
| linkage class |
no |
external |
(HTML table courtesy Robbins & Robbins' [USP] Chapter
2
webpage)
Summary of static reserved word
static keyword used in a variable declaration:
outside of any function:
/* x is static data and allocated in the static region of the memory image,
and it has external linkage */
/* linkage class: ?
storage class: ? */
int x;
/* x is STILL static data, but now has internal linkage and thus cannot be
referenced by another module (.o file) */
/* akin to "private" in C++ or Java */
/* linkage class: ?
storage class: ? */
static int x;
inside of any function:
void f() {
/* x is allocated on the stack (i.e., it is not static data) and
this particular x can only be referenced within the body of
this function */
/* linkage class: ?
storage class: ? */
int x;
/* x is now static data and allocated in the static region of the memory
image */
/* linkage class: ?
storage class: ? */
static int x;
}
static keyword used in a function definition/declaration:
/* f() has external linkage and thus can be referenced by another module
(i.e., .o file) */
/* linkage class: ?
storage class: ? */
void f();
/* f() has internal linkage and thus cannot be referenced by another module
(i.e., .o file) */
/* linkage class: ?
storage class: ? */
void static f();
Bubblesort storage class exercise
- for each object and function in the following code, give the
storage and linkage class where appropriate
- ref. [USP] program 2.5 (p. 41) and exercise 2.20 (p. 42)
/* a function which sorts an array of integers and
counts the number of interchanges made in the process */
static int count = 0;
/* return true if interchanges are made */
static int onepass (int a[], int n) {
int i;
int interchanges = 0;
int temp;
for (i = 0; i < n-1; i++)
if (a[i] > a[i+1]) {
temp = a[i];
a[i] = a[i+1];
a[i+1] = temp;
interchanges = 1;
count++;
}
return interchanges;
}
void clearcount (void) {
count = 0;
}
int getcount (void) {
return count;
}
/* sort a in ascending order */
void bubblesort (int a[], int n) {
int i;
for (i = 0; i < n-1; i++)
if (!onepass (a, n-i))
break;
}
count is a static variable with internal linkage (note
use of static modifier for linkage, not storage)
all other variables use automatic storage with no linkage
onepass does not have a storage class; its linkage is
internal
all other functions have external linkage; functions do not have a
storage class
Synchronization
Thread-safe functions
- static variables make the use of multiple threads unsafe
- char* strtok (char* restrict s1, const char* restrict delimiter);
- first and subsequent calls are different
- tokenizes string in place (i.e., does not allocate new space for
tokens)
- strtok is not thread-safe because it uses a static
pointer
- graphical depiction of string before and after call to
strtok
before:
(regenerated with minor modifications from [USP] Fig. 2.3, p. 36)
after:
(regenerated with minor modifications from [USP] Fig. 2.4, p. 36)
index into the string being tokenized (e.g., wordcount, wordaverage)
- use POSIX thread-safe function strtok_r
(_r stands for reentrant)
- moral of the story: avoid using static storage
makeargv
- ref. [USP] §2.6
(pp. 31-38)
- three versions
- char** makeargv (char* s);
- int makeargv (char* s, char*** argvp);
- int makeargv (const char* s, const char* delimiters, char*** argvp);
- for instance, ./a.out -c tom and -m jerry
- importance of cleaning up after yourself; [USP] example 2.19 on p. 38
(freemakeargv.c)
- [USP] exercise 2.24 on p. 51 (getpaths.c)
Self-study
- re-read [USP] §2.9 (pp. 42-48)
- download, compile, and run codes
- convince yourself you understand how the list works
- exercise in implementing the third version of makeargv
References
| [COPL] |
R.W. Sebesta.
Concepts of Programming Languages.
Addison-Wesley, Boston, MA, Sixth edition, 2003. |
| [OSCJ] |
A. Silberschatz, P.B. Galvin, and G. Gagne.
Operating Systems Concepts with Java.
John Wiley and Sons, Inc., Seventh edition, 2007. |
| [OSIDP] |
W. Stallings.
Operating Systems: Internals and Design Principles.
Prentice Hall, Upper Saddle River, NJ, Sixth edition, 2009.
|
| [USP] |
K.A. Robbins and S. Robbins.
UNIX Systems Programming: Concurrency, Communication, and Threads.
Prentice Hall, Upper Saddle River, NJ, Second edition, 2003.
|
|