### Compile and Run Pthread Example Source: https://greenteapress.com/thinkos/html/thinkos011 Shell commands to compile a C program that uses Pthreads and then run the executable. It includes the `make` command and the direct GCC compilation command with the `-lpthread` flag. ```bash $ make counter gcc -Wall counter.c -o counter -lpthread $ ./counter ``` -------------------------------- ### C: Allocate and Fill Array on Stack Source: https://greenteapress.com/thinkos/html/thinkos007 This C function allocates an integer array of size 100 on the stack and initializes each element with its index. It serves as a setup for demonstrating memory access errors in subsequent functions. ```c void f1() { int i; int array[100]; for (i=0; i<100; i++) { array[i] = i; } } ``` -------------------------------- ### Inspect Object Code with nm command Source: https://greenteapress.com/thinkos/html/thinkos003 The 'nm' command is used to list symbols from object files. This example shows how to inspect the 'hello.o' file to see the defined and used symbols, such as 'main' and 'puts'. ```bash $ nm hello.o ``` -------------------------------- ### Get Seconds Function for Timing (C) Source: https://greenteapress.com/thinkos/html/thinkos009 This C function, `get_seconds`, utilizes the `clock_gettime` system call to obtain the process CPU time. It converts the time into seconds, returning the result as a double-precision floating-point number for precise timing measurements. ```C double get_seconds(){ struct timespec ts; clock_gettime(CLOCK_PROCESS_CPUTIME_ID, &ts); return ts.tv_sec + ts.tv_nsec / 1e9; } ``` -------------------------------- ### List Current Terminal Processes with 'ps' Source: https://greenteapress.com/thinkos/html/thinkos004 This command lists processes associated with the current terminal. It displays the Process ID (PID), the terminal (TTY) from which the process was started, the cumulative CPU time used by the process, and the command name. ```bash ps ``` -------------------------------- ### C Example: Using Semaphore as a Mutex Source: https://greenteapress.com/thinkos/html/thinkos013 Demonstrates how to use a semaphore as a mutex. The semaphore is initialized to 1, and `semaphore_wait` and `semaphore_signal` are used to protect a critical section of code, ensuring only one thread can execute it at a time. ```c Semaphore *mutex = make_semaphore(1); semaphore_wait(mutex); // protected code goes here semaphore_signal(mutex); ``` -------------------------------- ### Example x86 Assembly Code Generated by gcc Source: https://greenteapress.com/thinkos/html/thinkos003 This is an example of the assembly code that might be generated by gcc for a simple C program. The code is specific to the x86 architecture and includes directives for sections, symbols, and function definitions. ```assembly .file "hello.c" .section .rodata .LC0: .string "Hello World" .text .globl main .type main, @function main: .LFB0: .cfi_startproc pushq %rbp .cfi_def_cfa_offset 16 .cfi_offset 6, -16 movq %rsp, %rbp .cfi_def_cfa_register 6 movl $.LC0, %edi call puts movl $0, %eax popq %rbp .cfi_def_cfa 7, 8 ret .cfi_endproc .LFE0: .size main, .-main .ident "GCC: (Ubuntu/Linaro 4.7.3-1ubuntu1) 4.7.3" .section .note.GNU-stack,"",@progbits ``` -------------------------------- ### C: Array Access with Floats Source: https://greenteapress.com/thinkos/html/thinkos007 This C code snippet modifies the previous example to use an array of floats. When out-of-bounds reads occur and the data is interpreted as integers, it highlights how data types affect the interpretation of memory content, leading to difficult-to-debug issues. ```c void f1() { int i; float array[100]; // Changed to float for (i=0; i<100; i++) { array[i] = i; } } void f2() { int x = 17; int array[10]; // Still int array for demonstration int y = 123; printf("%d\n", array[-2]); printf("%d\n", array[-1]); printf("%d\n", array[10]); printf("%d\n", array[11]); } ``` -------------------------------- ### Static Local Variable Counter in C Source: https://greenteapress.com/thinkos/html/thinkos005 This C function demonstrates the use of a static local variable. The 'counter' variable retains its value across function calls because it is allocated in the global segment, not on the stack. The initialization 'static int counter = 0;' occurs only once when the program starts. ```c int times_called() { static int counter = 0; counter++; return counter; } ``` -------------------------------- ### C Static Type Function Example Source: https://greenteapress.com/thinkos/html/thinkos003 Illustrates a C function with static typing, where parameter and return types (integers in this case) are explicitly declared. This allows for compile-time type checking, ensuring the addition operator is valid for the given types and preventing runtime errors. ```c int add(int x, int y) { return x + y; } ``` -------------------------------- ### Define Shared Data Structure for Threads Source: https://greenteapress.com/thinkos/html/thinkos011 A C typedef statement defining a structure to hold data shared between threads. In this example, it contains a single integer 'counter'. ```c typedef struct { int counter; } Shared; ``` -------------------------------- ### Open, Read, and Close a File in C Source: https://greenteapress.com/thinkos/html/thinkos006 Demonstrates how to open a file for reading, read a single character, and then close the file using standard C library functions. This involves using `fopen`, `fgetc`, and `fclose`. ```c FILE *fp = fopen("/home/downey/file.txt", "r"); char c = fgetc(fp); fclose(fp); ``` -------------------------------- ### Open, Write, and Close a File in C Source: https://greenteapress.com/thinkos/html/thinkos006 Illustrates how to open a file for writing, write a single character to it, and then close the file using C standard library functions. This involves `fopen`, `fputc`, and `fclose`. ```c FILE *fp = fopen("/home/downey/file.txt", "w"); fputc('b', fp); fclose(fp); ``` -------------------------------- ### Demonstrate Process Memory Segments in C Source: https://greenteapress.com/thinkos/html/thinkos005 This C program illustrates the memory layout of a process by printing the addresses of the code segment (main function), global variable, local variable, heap-allocated memory, and a string literal. It uses printf with the %p format specifier to display addresses in hexadecimal. ```c #include #include int global; int main () { int local = 5; void *p = malloc(128); char *s = "Hello, World"; printf ("Address of main is %p\n", main); printf ("Address of global is %p\n", &global); printf ("Address of local is %p\n", &local); printf ("p points to %p\n", p); printf ("s points to %p\n", s); } ``` -------------------------------- ### List All Processes with 'ps -e' Source: https://greenteapress.com/thinkos/html/thinkos004 This command lists all running processes on the system, including those not associated with the current terminal. It provides the same information as the default 'ps' command (PID, TTY, TIME, CMD) but for every process. Be aware that this may reveal sensitive information. ```bash ps -e ``` -------------------------------- ### Compile C Program with Pthread Library using GCC Source: https://greenteapress.com/thinkos/html/thinkos011 This command demonstrates how to compile a C source file (array.c) using GCC, linking it with the Pthread library. The flags specify debugging information (-g), optimization (-O2), the output executable name (-o array), and the Pthread library linkage (-lpthread). ```bash gcc -g -O2 -o array array.c -lpthread ``` -------------------------------- ### Queue Initialization with Mutex Creation (C) Source: https://greenteapress.com/thinkos/html/thinkos012 Illustrates the `make_queue` function updated to initialize the new `mutex` member. It calls `make_mutex()` to create and assign a mutex to the queue, preparing it for thread-safe operations. ```c Queue *make_queue(int length) { Queue *queue = (Queue *) malloc(sizeof(Queue)); queue->length = length; queue->array = (int *) malloc(length * sizeof(int)); queue->next_in = 0; queue->next_out = 0; queue->mutex = make_mutex(); //-- new return queue; } ``` -------------------------------- ### Compile and Run a C Program with gcc Source: https://greenteapress.com/thinkos/html/thinkos003 This snippet shows the basic command to compile a C source file into an executable and then run it. By default, gcc creates an executable named 'a.out'. ```c #include int main() { printf("Hello World\n"); } ``` ```bash $ gcc hello.c $ ./a.out ``` -------------------------------- ### Python Dynamic Type Function Example Source: https://greenteapress.com/thinkos/html/thinkos003 Demonstrates a Python function with dynamic typing, where variable types are not explicitly declared and are determined at runtime. This function accepts two arguments and returns their sum, working with any types that support the addition operator. ```python def add(x, y): return x + y ``` -------------------------------- ### Initialize Queue with Condition Variable (C) Source: https://greenteapress.com/thinkos/html/thinkos012 Initializes a new Queue structure, including the allocation and creation of the 'nonempty' condition variable using `make_cond()`. This ensures the condition variable is ready for use when the queue is created. ```c Queue *make_queue(int length) { Queue *queue = (Queue *) malloc(sizeof(Queue)); queue->length = length; queue->array = (int *) malloc(length * sizeof(int)); queue->next_in = 0; queue->next_out = 0; queue->mutex = make_mutex(); queue->nonempty = make_cond(); //-- new return queue; } ``` -------------------------------- ### Cache Performance Measurement Loop (C) Source: https://greenteapress.com/thinkos/html/thinkos009 This C code snippet demonstrates the core loop for measuring cache performance. It iterates through an array, performing read and write operations, and measures the total CPU time consumed. The outer do-while loop ensures sufficient time is accumulated for accurate measurement. ```C iters = 0; do { sec0 = get_seconds(); for (index = 0; index < limit; index += stride) array[index] = array[index] + 1; iters = iters + 1; sec = sec + (get_seconds() - sec0); } while (sec < 0.1); ``` -------------------------------- ### Initialize Condition Variable (C) Source: https://greenteapress.com/thinkos/html/thinkos012 Allocates memory for a `Cond` structure, initializes it using `pthread_cond_init`, and returns a pointer to the newly created condition variable. Error handling is included for the initialization process. ```c Cond *make_cond() { Cond *cond = check_malloc(sizeof(Cond)); int n = pthread_cond_init(cond, NULL); if (n != 0) perror_exit("make_cond failed"); return cond; } ``` -------------------------------- ### Create Multiple Child Threads Source: https://greenteapress.com/thinkos/html/thinkos011 C code demonstrating the creation of multiple child threads. It initializes a shared data structure and then uses a loop with the `make_thread` wrapper to create a specified number of threads. ```c int i; pthread_t child[NUM_CHILDREN]; Shared *shared = make_shared(1000000); for (i=0; iarray[queue->next_in] = item; queue->next_in = queue_incr(queue, queue->next_in); } ``` -------------------------------- ### Shared Structure Definition and Initialization (C) Source: https://greenteapress.com/thinkos/html/thinkos012 Defines a `Shared` structure to hold the queue pointer and provides a function `make_shared` to allocate and initialize this structure, including creating the underlying queue with a specified length. ```c typedef struct { Queue *queue; } Shared; Shared *make_shared() { Shared *shared = check_malloc(sizeof(Shared)); shared->queue = make_queue(QUEUE_LENGTH); return shared; } ``` -------------------------------- ### Queue Initialization with Semaphores (C) Source: https://greenteapress.com/thinkos/html/thinkos013 Initializes a 'Queue' structure for the Producer-Consumer problem using semaphores. It allocates memory for the queue and its array, and initializes the mutex, items, and spaces semaphores with appropriate initial values. ```c Queue *make_queue(int length) { Queue *queue = (Queue *) malloc(sizeof(Queue)); queue->length = length; queue->array = (int *) malloc(length * sizeof(int)); queue->next_in = 0; queue->next_out = 0; queue->mutex = make_semaphore(1); queue->items = make_semaphore(0); queue->spaces = make_semaphore(length-1); return queue; } ``` -------------------------------- ### Semaphore Initialization using Mutex and Condition Variable (C) Source: https://greenteapress.com/thinkos/html/thinkos013 Initializes a 'Semaphore' structure that uses a mutex and a condition variable. It allocates memory for the semaphore, sets its initial value and wakeups count, and creates the associated mutex and condition variable. ```c Semaphore *make_semaphore(int value) { Semaphore *semaphore = check_malloc(sizeof(Semaphore)); semaphore->value = value; semaphore->wakeups = 0; semaphore->mutex = make_mutex(); semaphore->cond = make_cond(); return semaphore; } ``` -------------------------------- ### Create and Initialize POSIX Mutex Source: https://greenteapress.com/thinkos/html/thinkos011 This C function, 'make_mutex', allocates memory for a Mutex object and initializes it using 'pthread_mutex_init'. It includes error handling to check if the initialization was successful, exiting the program with an error message if it fails. The function returns a pointer to the initialized mutex. ```c Mutex *make_mutex() { Mutex *mutex = check_malloc(sizeof(Mutex)); int n = pthread_mutex_init(mutex, NULL); if (n != 0) perror_exit("make_lock failed"); return mutex; } ``` -------------------------------- ### Queue Initialization in C Source: https://greenteapress.com/thinkos/html/thinkos012 Allocates memory for a Queue structure and its internal array, initializing the fields for a new queue. The length is incremented by 1 to accommodate the circular buffer logic. ```c Queue *make_queue(int length) { Queue *queue = (Queue *) malloc(sizeof(Queue)); queue->length = length + 1; queue->array = (int *) malloc(length * sizeof(int)); queue->next_in = 0; queue->next_out = 0; return queue; } ``` -------------------------------- ### Create Thread using Pthread Wrapper Source: https://greenteapress.com/thinkos/html/thinkos011 A C function that wraps `pthread_create` to simplify thread creation and add error checking. It takes a function pointer for the thread's entry point and a pointer to shared data, returning a thread identifier. ```c pthread_t make_thread(void *(*entry)(void *), Shared *shared) { int n; pthread_t thread; n = pthread_create(&thread, NULL, entry, (void *)shared); if (n != 0) { perror("pthread_create failed"); exit(-1); } return thread; } ``` -------------------------------- ### Unpack Floating-Point Number Components in C Source: https://greenteapress.com/thinkos/html/thinkos007 This C code snippet demonstrates how to unpack the sign, exponent, and coefficient of a 32-bit IEEE floating-point number. It utilizes a union to reinterpret the float as an unsigned integer and employs bitwise operations for extraction. The output shows the extracted sign bit, exponent (with bias), and coefficient. ```c union { float f; unsigned int u; } p; p.f = -13.0; unsigned int sign = (p.u >> 31) & 1; unsigned int exp = (p.u >> 23) & 0xff; unsigned int coef_mask = (1 << 23) - 1; unsigned int coef = p.u & coef_mask; printf("%d\n", sign); printf("%d\n", exp); printf("0x%x\n", coef); ``` -------------------------------- ### Generate Assembly Code from C Source using gcc -S flag Source: https://greenteapress.com/thinkos/html/thinkos003 This command utilizes the '-S' flag with gcc to compile the C source file and generate human-readable assembly code (a '.s' file). This is useful for understanding low-level code generation. ```bash $ gcc hello.c -S ``` -------------------------------- ### Calculating Average Miss Penalty (C) Source: https://greenteapress.com/thinkos/html/thinkos009 This C code snippet calculates the average miss penalty per access in nanoseconds. It uses the accumulated time (`sec`) from the isolation loop, the total number of iterations (`iters`), and the number of elements accessed per iteration (`limit / stride`), to derive the final miss penalty value. ```C sec * 1e9 / iters / limit * stride ``` -------------------------------- ### Include POSIX Threads and Semaphore Headers in C Source: https://greenteapress.com/thinkos/html/thinkos011 This code snippet shows the necessary header files to include when working with POSIX Threads (Pthreads) and semaphores in a C program. These headers provide access to the Pthreads API and semaphore functions, essential for multi-threaded programming. ```c #include #include #include #include ``` -------------------------------- ### Check Malloc Return Value in C Source: https://greenteapress.com/thinkos/html/thinkos008 This C code snippet demonstrates how to check the return value of the malloc function to ensure memory allocation was successful. It includes error handling using perror and exits the program with an error code if allocation fails. ```c void *p = malloc(size); if (p == NULL) { perror("malloc failed"); exit(-1); } ``` -------------------------------- ### Generate Object Code from C Source using gcc -c flag Source: https://greenteapress.com/thinkos/html/thinkos003 This command uses the '-c' flag with gcc to compile the C source file into object code (a '.o' file) without linking it into an executable. Object code can be linked later. ```bash $ gcc hello.c -c ``` -------------------------------- ### Initialize Shared Data Structure with Mutex Source: https://greenteapress.com/thinkos/html/thinkos011 This C function initializes a 'Shared' data structure, setting the counter to zero and creating a new mutex object using 'make_mutex()'. This ensures that the shared data is properly set up with synchronization primitives before being used by multiple threads. ```c Shared *make_shared(int end) { Shared *shared = check_malloc(sizeof(Shared)); shared->counter = 0; shared->mutex = make_mutex(); //-- this line is new return shared; } ```