+ All Categories
Home > Documents > Today… Project 1 (Shell) due today Homework #2 due Friday (January 30) Questions… BYU CS...

Today… Project 1 (Shell) due today Homework #2 due Friday (January 30) Questions… BYU CS...

Date post: 19-Dec-2015
Category:
Upload: gyles-small
View: 215 times
Download: 1 times
Share this document with a friend
88
Today… Project 1 (Shell) due today Homework #2 due Friday (January 30) Questions… BYU CS 345 Threads 1
Transcript
Page 1: Today… Project 1 (Shell) due today Homework #2 due Friday (January 30) Questions… BYU CS 345Threads1.

Threads 1

Today…

Project 1 (Shell) due today Homework #2 due Friday (January 30) Questions…

BYU CS 345

Page 2: Today… Project 1 (Shell) due today Homework #2 due Friday (January 30) Questions… BYU CS 345Threads1.

Chapter 3 - Processes 2BYU CS 345

7. Operating System Control Tables

Control Tables

Task Control Block

Page 3: Today… Project 1 (Shell) due today Homework #2 due Friday (January 30) Questions… BYU CS 345Threads1.

Chapter 3 - Processes 3BYU CS 345

Task Control Block (tcb)P2 - Tasking

// task control blocktypedef struct // task control block{ char* name; // task name

int (*task)(int,char**); // task addressint state; // task stateint priority; // task priority (P2)int argc; // task argument count (P1)char** argv; // task argument pointers (P1)

int signal; // task signals (P1)void (*sigContHandler)(void); // task mySIGCONT handler (P1)void (*sigIntHandler)(void); // task mySIGINT handler (P1)void (*sigKillHandler)(void); // task mySIGKILL handler (P1)void (*sigTermHandler)(void); // task mySIGTERM handler (P1)void (*sigTstpHandler)(void); // task mySIGTSTP handler (P1)

TID parent; // task parentint RPT; // task root page table (P4)int cdir; // task directory (P6)Semaphore *event; // blocked task semaphore (P2)void* stack; // task stack (P2)jmp_buf context; // task context pointer (P2)

} TCB;

Page 4: Today… Project 1 (Shell) due today Homework #2 due Friday (January 30) Questions… BYU CS 345Threads1.

Processes and Threads

Chapter 4

Page 5: Today… Project 1 (Shell) due today Homework #2 due Friday (January 30) Questions… BYU CS 345Threads1.

BYU CS 345 Threads 5

CS 345

Stalling’s Chapter # Project

1: Computer System Overview2: Operating System Overview

4 P1: Shell

3: Process Description and Control4: Threads

4 P2: Tasking

5: Concurrency: ME and Synchronization6: Concurrency: Deadlock and Starvation

6 P3: Jurassic Park

7: Memory Management8: Virtual memory

6 P4: Virtual Memory

9: Uniprocessor Scheduling10: Multiprocessor and Real-Time Scheduling

6 P5: Scheduling

11: I/O Management and Disk Scheduling12: File Management

8 P6: FAT

Student Presentations 6

Page 6: Today… Project 1 (Shell) due today Homework #2 due Friday (January 30) Questions… BYU CS 345Threads1.

Threads 6

Chapter 4 Learning Outcomes

Understand the distinction between process and thread. Describe the basic design issues for threads. Explain the difference between user-level threads and

kernel-level threads. Describe the thread management facility in Windows 7. Describe the thread management facility in Solaris. Describe the thread management facility in Linux.

BYU CS 345

Page 7: Today… Project 1 (Shell) due today Homework #2 due Friday (January 30) Questions… BYU CS 345Threads1.

Threads 7BYU CS 345

Questions…

1. What is a Process?

2. What is a Thread?

3. What are the different types of Threads?

4. What are the benefits of Threads?

5. What are possible Thread States?

6. What is a RPC?

7. How are Threads managed?

8. How are ULT’s created in C?

Page 8: Today… Project 1 (Shell) due today Homework #2 due Friday (January 30) Questions… BYU CS 345Threads1.

Threads 8BYU CS 345

What is moving around?

Page 9: Today… Project 1 (Shell) due today Homework #2 due Friday (January 30) Questions… BYU CS 345Threads1.

Threads 9BYU CS 345

1. What is a Process?

Traditionally, a process is considered an instance of a computer program that is being executed.

A process contains System resources: program code, user data, buffers,

devices, I/O channels, files Current activity: CPU, registers, state, execution

path, “On the clock”, interleaved with other processes Can resources and CPU activity be treated

independently? Unit of resource ownership process or task Unit of execution thread or lightweight process

Processes

Page 10: Today… Project 1 (Shell) due today Homework #2 due Friday (January 30) Questions… BYU CS 345Threads1.

Threads 10BYU CS 345

Processes

Resources owned by a process: code ("text"), data (VM), stack, heap, files, tables (signals, semaphores, buffers, I/O,…)

Context switching processes has a significant amount of overhead: Tables have to be flushed from the processor when

context switching. Processes share information only through pipes and

shared memory.

Processes

Page 11: Today… Project 1 (Shell) due today Homework #2 due Friday (January 30) Questions… BYU CS 345Threads1.

Threads 11BYU CS 345

2. What is a Thread?

A thread of execution Smallest unit of processing that can be scheduled by an

operating system Threads reduce overhead by sharing the

resources of a process. Switching can happen more frequently and efficiently. Sharing information is not so "difficult" anymore -

everything can be shared. A Thread is an independent program counter

operating within a process. Sometimes called a lightweight process (LWP) A smaller execution unit than a process.

Threads

Page 12: Today… Project 1 (Shell) due today Homework #2 due Friday (January 30) Questions… BYU CS 345Threads1.

Threads 12BYU CS 345

Threads and Processes

one processone thread

multiple processesone thread per process

multiple processesmultiple threads per process

one processmultiple threads

Threads

Page 13: Today… Project 1 (Shell) due today Homework #2 due Friday (January 30) Questions… BYU CS 345Threads1.

Threads 13BYU CS 345

Multi-threading

Operating system or user may support multiple threads of execution within a single process. Traditional approach is single process, single

threaded. Current support for mult-process, mult-threading.

Examples: MS-DOS: single user process, single thread. UNIX: multiple processes, one thread per process. Java run-time environment: one process, multiple

threads. Windows 2000 (W2K), Solaris, Linux, Mach, and

OS/2: multiple processes, each supports multiple threads.

Threads

Page 14: Today… Project 1 (Shell) due today Homework #2 due Friday (January 30) Questions… BYU CS 345Threads1.

Threads 14BYU CS 345

3. What Types of Threads?

There are two types of threads: User-space (ULT) and Kernel-space (KLT).

A thread consists of: a thread execution state (Running, Ready, etc.) a context (program counter, register set.) an execution stack. some per-tread static storage for local variables. access to the memory and resources of its process (shared with

all other threads in that process.) OS resources (open files, signals, etc.)

Thus, all of the threads of a process share the state and resources of the parent process (memory space and code section.)

Threads

Page 15: Today… Project 1 (Shell) due today Homework #2 due Friday (January 30) Questions… BYU CS 345Threads1.

Threads 15BYU CS 345

4. What are the Benefits of Threads?

A process has at least one thread of execution May launch other threads which execute concurrently

with the process. Threads of a process share the instructions (code) and

process context (data). Key benefits:

Far less time to create/terminate. Switching between threads is faster. No memory management issues, etc. Can enhance communication efficiency. Simplify the structure of a program.

Threads

Page 16: Today… Project 1 (Shell) due today Homework #2 due Friday (January 30) Questions… BYU CS 345Threads1.

Threads 16BYU CS 345

Multi-threaded Process

(a) Task graph of a program (b) Thread structure of a task

Thread 1 Thread 2 Thread 3

Sync

Sync

Spawn additional threads

Threads

Page 17: Today… Project 1 (Shell) due today Homework #2 due Friday (January 30) Questions… BYU CS 345Threads1.

Threads 17BYU CS 345

Exclusive/Shared Resources

ThreadControlBlock

UserStack

UserStack

KernelStack

KernelStack

UserAddressSpace

UserAddressSpace

ProcessControlBlock

ProcessControlBlock

Thread

Single-ThreadedProcess Model

MultithreadedProcess Model

ThreadControlBlock

UserStack

KernelStack

Thread

ThreadControlBlock

UserStack

KernelStack

Thread

Threads

Page 18: Today… Project 1 (Shell) due today Homework #2 due Friday (January 30) Questions… BYU CS 345Threads1.

Threads 18BYU CS 345

Using Threads

Multiple threads in a single process Separate control blocks for the process and each thread Can quickly switch between threads Can communicate without invoking the kernel

Four Examples Foreground/Background – spreadsheet updates Asynchronous Processing – Backing up in background Faster Execution – Read one set of data while processing

another set Organization – For a word processing program, may allow one

thread for each file being edited

Threads

Page 19: Today… Project 1 (Shell) due today Homework #2 due Friday (January 30) Questions… BYU CS 345Threads1.

Threads 19BYU CS 345

5. What are Possible Thread States?

Thread operations Spawn – Creating a new thread Block – Waiting for an event Unblock – Event happened, start new Finish – This thread is completed

Generally, it is desirable that a thread can block without blocking the remaining threads in the process

Allow the process to start two operations at once, each thread blocks on the appropriate event

Must handle synchronization between threads System calls or local subroutines Thread generally responsible for getting/releasing locks, etc.

Threads

Page 20: Today… Project 1 (Shell) due today Homework #2 due Friday (January 30) Questions… BYU CS 345Threads1.

Threads 20BYU CS 345

6. What is a RPC?RPC’s

“A remote procedure call (RPC) is an inter-process communication that allows a computer program to cause a subroutine or procedure to execute in another address space (commonly on another computer on a shared network) without the programmer explicitly coding the details for this remote interaction.”

1. Client calls the client stub (stack).2. Client stub packs (marshalls) parameters.3. Client's OS sends message to server.4. Server OS passes packets to server stub.5. Server stub unpacks (unmarshalls) message.6. Server stub calls the server procedure.7. Reply traces in the reverse direction.

Page 21: Today… Project 1 (Shell) due today Homework #2 due Friday (January 30) Questions… BYU CS 345Threads1.

Threads 21BYU CS 345

7. How are Threads Managed?

How should threads be scheduled compared to processes? Equal to processes Within the parent processes quantum

How are threads implemented? kernel support (system calls) user level threads

What about mutual exclusion? Process resources are shared Data coherency

Thread Issues

Page 22: Today… Project 1 (Shell) due today Homework #2 due Friday (January 30) Questions… BYU CS 345Threads1.

Threads 22BYU CS 345

8. User-Level Threads

User-level avoids the kernel and manages the tables itself. Often this is called "cooperative multitasking" where

the task defines a set of routines that get "switched to" by manipulating the stack pointer.

Typically each thread "gives-up" the CPU by calling an explicit switch, sending a signal or doing an operation that involves the switcher.

Also, a timer signal can force switches. User threads typically can switch faster than kernel

threads [however, Linux kernel threads' switching is actually pretty close in performance].

ULT’s

Page 23: Today… Project 1 (Shell) due today Homework #2 due Friday (January 30) Questions… BYU CS 345Threads1.

Threads 23BYU CS 345

User-Level Threads

Disadvantages. User-space threads have a problem that a single thread can

monopolize the timeslice thus starving the other threads within the task.

Also, it has no way of taking advantage of SMPs (Symmetric MultiProcessor systems, e.g. dual-/quad-Pentiums).

Lastly, when a thread becomes I/O blocked, all other threads within the task lose the timeslice as well.

Solutions/work arounds. Timeslice monopolization can be controlled with an external

monitor that uses its own clock tick. Some SMPs can support user-space multithreading by firing up

tasks on specified CPUs then starting the threads from there [this form of SMP threading seems tenuous, at best].

Some libraries solve the I/O blocking problem with special wrappers over system calls, or the task can be written for nonblocking I/O.

ULT’s

Page 24: Today… Project 1 (Shell) due today Homework #2 due Friday (January 30) Questions… BYU CS 345Threads1.

Threads 24BYU CS 345

Kernel-Level Threads

KLTs often are implemented in the kernel using several tables (each task gets a table of threads).

The kernel schedules each thread within the timeslice of each process.

There is a little more overhead with mode switching from user->kernel-> user and loading of larger contexts, but initial performance measures indicate a negligible increase in time.

Advantages. Since the clocktick will determine the switching times, a task is

less likely to hog the timeslice from the other threads within the task.

I/O blocking is not a problem. If properly coded, the process automatically can take advantage

of SMPs and will run incrementally faster with each added CPU.

KLT’s

Page 25: Today… Project 1 (Shell) due today Homework #2 due Friday (January 30) Questions… BYU CS 345Threads1.

Threads 25BYU CS 345

User-Level and Kernel-Level Threads

Thread Management

Page 26: Today… Project 1 (Shell) due today Homework #2 due Friday (January 30) Questions… BYU CS 345Threads1.

Threads 26BYU CS 345

Thread Management

Some implementations support both ULT and KLT threads. Can take advantage of each to the running task. Since Linux's kernel-space threads nearly perform as

well as user-space, the only advantage of using user-threads would be the cooperative multitasking.

OS system calls could each be written as a thread or OS could be single threaded.

Advantages: Speed and Concurrency Disadvantages: Mutual exclusion and complexity

Thread Management

Page 27: Today… Project 1 (Shell) due today Homework #2 due Friday (January 30) Questions… BYU CS 345Threads1.

Threads 27BYU CS 345

Thread Problems

In many other multithreaded OSs, threads are not processes merely parts of a parent task.

Therefore, if a thread calls fork()’s or execve()'s some external program, the whole task could be replaced.

The POSIX 1c standard defines a thread calling fork() to duplicate only the calling thread in the new process; and an execve() from a thread would stop all threads of that process.

Having two different implementations and schedulers for processes is a flaw that has perpetuated from implementation to implementation.

Some multitasking OSs have opted not to support threads due to these problems (not to mention the effort needed to make the kernel and libraries 100% reentrant).

For example, Windows NT opts not to support POSIX-compliant threads (Windows NT does support threads but they are not POSIX compliant).

Page 28: Today… Project 1 (Shell) due today Homework #2 due Friday (January 30) Questions… BYU CS 345Threads1.

Threads 28BYU CS 345

Thread Problems

Most people have a hard enough time understanding tasks.

“Chopped up tasks" or threads is difficult to envision. "What can be threaded in my app?". Deciding what to thread can be very laborious.

Another problem is locking. All the nightmares about sharing, locking, deadlock, race

conditions, etc. come vividly alive in threads. Processes don't usually have to deal with this, since most

shared data is passed through pipes. Threads can share file handles, pipes, variables, signals, etc. Test and duplicate error conditions can cause more gray hair

than a wayward child.

Page 29: Today… Project 1 (Shell) due today Homework #2 due Friday (January 30) Questions… BYU CS 345Threads1.

Threads 29BYU CS 345

Thread Support

As of 1.3.56, Linux has supported kernel-level multithreading. User-level thread libraries around as early as 1.0.9. On-going effort to refine and make the kernel more

reentrant. With the introduction of 2.1.x, the memory space is

being revised so that the kernel can access the user memory more quickly.

Windows NT opts not to support POSIX-compliant threads (Windows NT does support threads but they are not POSIX compliant).

Page 30: Today… Project 1 (Shell) due today Homework #2 due Friday (January 30) Questions… BYU CS 345Threads1.

Threads 30BYU CS 345

Thread Review

How does a thread differ from a process? Resource ownership Smallest unit of processing that can be scheduled by

an operating system What are the implications of having an

independent program counter? Each thread has its own stack. Code and global data belong to the process and are

shared among threads. Threads “own” local data.

Thread state is defined by processor registers and the stack.

C Threads

Page 31: Today… Project 1 (Shell) due today Homework #2 due Friday (January 30) Questions… BYU CS 345Threads1.

Project 2 - Tasking

Page 32: Today… Project 1 (Shell) due today Homework #2 due Friday (January 30) Questions… BYU CS 345Threads1.

Project 2 - Tasking 32BYU CS 345

Project 2

Change the scheduler from a 2 state to a 5 state scheduler using semaphores with priority queues.

int scheduler() in os345.c semWait(), semSignal, semTryLock in os345semaphores.c

Tasks are functions and are added to the task scheduler ready queue via the “createTask()” function.

The first task scheduled is your shell from Project 1. The “SWAP” directive replaces clock interrupts for context

switching between tasks (cooperative scheduling). Context switching directives may be placed anywhere in

your user task code. SWAP, SEM_SIGNAL, SEM_WAIT, SEM_TRYLOCK

P2 - Tasking

Page 33: Today… Project 1 (Shell) due today Homework #2 due Friday (January 30) Questions… BYU CS 345Threads1.

Project 2 - Tasking 33BYU CS 345

Project 2 (continued…)

The highest priority, unblocked, ready task should always be executing.

Tasks of the same priority should be scheduled in a round-robin, FIFO fashion.

Any change of events (SEM_SIGNAL) should cause a context switch.

To simulate interrupts, character inputs and timers need to be “polled” in the scheduling loop.

void pollInterrupts() in OS345p1.c Parsed command line arguments are passed to tasks (ie.

functions) via argc/argv variables.

P2 - Tasking

Page 34: Today… Project 1 (Shell) due today Homework #2 due Friday (January 30) Questions… BYU CS 345Threads1.

Project 2 - Tasking 34

Step 1: Priority Queue

Create a priority queue typedef int TID; // task ID

typedef int Priority; // task prioritytypedef int* PQueue; // priority queue

PQueue rq; // ready queuerq = (int*)malloc(MAX_TASKS * sizeof(int));rq[0] = 0; // init ready queue

Queue functions int enQ(PQueue q, TID tid, Priority p);

q priority queue (# | pr1/tid1 | pr2/tid2 | …)tid task idp task priorityint return tid

int deQ(PQueue q, TID tid);q priority queuetid find and delete tid from q

(tid == -1 find/delete highest priority)int deleted tid

(tid == -1 q empty or task not found)

BYU CS 345

Priority/TID

Priority/TID

Priority/TID

Priority/TID

# of entries

rq[5]

rq[4] 10 / 3

rq[3] 5 / 2

rq[2] 5 / 0

rq[1] 2 / 1

rq[0] 4

P2 - Tasking

Page 35: Today… Project 1 (Shell) due today Homework #2 due Friday (January 30) Questions… BYU CS 345Threads1.

Project 2 - Tasking 35

Step 2: Schedule w/Ready Queue

Create a ready priority queue PQueue rq; // ready queue

rq = (int*)malloc(MAX_TASKS * sizeof(int));rq[0] = 0; // init ready queue

Add new task to ready queue in createTask enQ(rq, tid, tcb[tid].priority); NOTE: priority count be internal to enQ/deQ

Change scheduler() to deQueue and then enQueue next task

if ((nextTask = deQ(rq, -1)) >= 0){

enQ(rq, nextTask);}

BYU CS 345

Priority/TID

Priority/TID

Priority/TID

Priority/TID

# of entries

rq[5]

rq[4] 10 / 3

rq[3] 5 / 2

rq[2] 5 / 0

rq[1] 2 / 1

rq[0] 4

P2 - Tasking

Page 36: Today… Project 1 (Shell) due today Homework #2 due Friday (January 30) Questions… BYU CS 345Threads1.

Project 2 - Tasking 36

2-State Scheduler

BYU CS 345

createTask()dispatch()

swapTask()

killTask()

NewReadyQueue

Running

Exit

P2 - Tasking

nextTask = enQueue(rq, deQueue(rq, -1));

Page 37: Today… Project 1 (Shell) due today Homework #2 due Friday (January 30) Questions… BYU CS 345Threads1.

Project 2 - Tasking 37

Step 3: 5-State Scheduling

BYU CS 345

Add priority queue to semaphore struct typedef struct semaphore // semaphore

{ struct semaphore* semLink; // link to next semaphorechar* name; // semaphore name (malloc)

int state; // state (count)int type; // type (binary/counting)int taskNum; // tid of creatorPQueue q; // blocked queue

} Semaphore;

Malloc semaphore queue in createSemaphore semaphore->q = (int*)malloc(MAX_TASKS * sizeof(int));

semaphore->q[0] = 0; // init queue

semWait: deQueue current task from ready queue and enQueue in semaphore queue

semSignal: deQueue task from blocked queue and enQueue in ready queue.

P2 - Tasking

Page 38: Today… Project 1 (Shell) due today Homework #2 due Friday (January 30) Questions… BYU CS 345Threads1.

Project 2 - Tasking 38

BlockedQueues

sem

Wait

()

sem

TryLo

ck()sem

Sig

nal(

)

5-State Scheduler

BYU CS 345

createTask()

dispatch()

swapTask()killTask()

NewReadyQueue

Running

Exit

#define SWAP swapTask();#define SEM_WAIT(s) semWait(s);#define SEM_SIGNAL(s) semSignal(s);#define SEM_TRYLOCK(s) semTryLock(s);

P2 - Tasking

Page 39: Today… Project 1 (Shell) due today Homework #2 due Friday (January 30) Questions… BYU CS 345Threads1.

Project 2 - Tasking 39BYU CS 345

Task Scheduling

Ready Priority Queue

Semaphore Priority Queue

Semaphore Priority Queue

Semaphore Priority Queue

SWAP

SEM_SIGNAL SEM_WAIT

SEM_SIGNAL SEM_WAIT

SEM_SIGNAL SEM_WAIT

Executing

Scheduler / Dispatcher

Scheduling

Page 40: Today… Project 1 (Shell) due today Homework #2 due Friday (January 30) Questions… BYU CS 345Threads1.

Project 2 - Tasking 40

Step 4: Counting Semaphore

BYU CS 345

Implement counting functionality to semaphores Add a 10 second timer (tics10sec) counting semaphore

to the polling routine (pollInterrupts). This can be done by including the <time.h> header and calling the C function time(time_t *timer). semSignal the tics10sec semaphore every 10 seconds.

Create a reentrant high priority task that blocks (SEM_WAIT) on the 10 second timer semaphore (tics10sec). When activated, output a message with the current task number and time and then block again.

P2 - Tasking

Page 41: Today… Project 1 (Shell) due today Homework #2 due Friday (January 30) Questions… BYU CS 345Threads1.

Project 2 - Tasking 41BYU CS 345

Task Control Block (tcb)P2 - Tasking

// task control blocktypedef struct // task control block{

char* name; // task nameint (*task)(int,char**); // task addressint state; // task state (P2)int priority; // task priority (P2)int argc; // task argument count (P1)char** argv; // task argument pointers (P1)int signal;

// task signals (P1)// void (*sigContHandler)(void); // task mySIGCONT handler

void (*sigIntHandler)(void); // task mySIGINT handler// void (*sigKillHandler)(void); // task mySIGKILL handler// void (*sigTermHandler)(void); // task mySIGTERM handler// void (*sigTstpHandler)(void); // task mySIGTSTP handler

TID parent; // task parentint RPT; // task root page table (P4)int cdir; // task directory (P6)Semaphore *event; // blocked task semaphore (P2)void* stack; // task stack (P1)jmp_buf context; // task context pointer (P1)

} TCB;

State = { NEW, READY, RUNNING, BLOCKED, EXIT }Priority = { LOW, MED, HIGH, VERY_HIGH, HIGHEST }

Pending semaphore when blocked.

Page 42: Today… Project 1 (Shell) due today Homework #2 due Friday (January 30) Questions… BYU CS 345Threads1.

Project 2 - Tasking 42

Step 5: List Tasks

BYU CS 345

Modify the list tasks command to display all tasks in the system queues in execution/priority order indicating the task name, if the task is ready, paused, executing, or blocked, and the task priority. If the task is blocked, list the reason for the block.

P2 - Tasking

Page 43: Today… Project 1 (Shell) due today Homework #2 due Friday (January 30) Questions… BYU CS 345Threads1.

Project 2 - Tasking 43

Step 6: Verification

BYU CS 345

The project2 command schedule timer tasks 1 through 9, 2 signal tasks and 2 “ImAlive” tasks. The tics10sec task about the current time every 10 seconds in a round robin order. The “ImAlive” tasks will periodically say hello. The high priority “Signal” tasks should respond immediately when semaphore signaled.

# Task Name Priority Time slice Blocking Semaphore

0 CLI w/pseudo-input interrupts 5 1 inBufferReady

1-9 TenSeconds 10 1 tics10sec

10 sTask1 20 1 sTask10

11 sTask2 20 1 sTask11

12 ImAlive 1 1 None

13 ImAlive 1 1 None

P2 - Tasking

Page 44: Today… Project 1 (Shell) due today Homework #2 due Friday (January 30) Questions… BYU CS 345Threads1.

Project 2 - Tasking 44

Step 7: Bonus Credit

BYU CS 345

Implement a buffered pseudo-interrupt driven character output and demonstrate that it works by implementing a my_printf function.

Implement time slices that adjust task execution times when scheduled.

createTask( "myShell", // task nameP1_shellTask, // task5, // task priorityargc, // task arg countargv // task argument pointers

);

#include <stdarg.h>void my_printf(char* fmt, ...){ va_list arg_ptr;

char pBuffer[128];char* s = pBuffer;va_start(arg_ptr, fmt);vsprintf(pBuffer, fmt, arg_ptr);while (*s) putIObuffer(*s++);va_end(arg_ptr);

} // end my_printf

P2 - Tasking

Page 45: Today… Project 1 (Shell) due today Homework #2 due Friday (January 30) Questions… BYU CS 345Threads1.

Project 2 - Tasking 45BYU CS 345

setjmp / longjmp

#include <setjmp.h> jmp_buf struct

stack pointer (sp), frame pointer (fp), and program counter (pc).

setjmp(jmp_buf env); saves the program state (sp, fp, pc) in env so that

longjmp() can restore them later. returns 0 value.

longjmp(jmp_buf env, int val); resets the registers to the values saved in env. longjmp() returns as if you have just called the

setjmp() call that saved env with non-zero value.

setjmp/longjmp

Page 46: Today… Project 1 (Shell) due today Homework #2 due Friday (January 30) Questions… BYU CS 345Threads1.

Project 2 - Tasking 46BYU CS 345

Multi-tasking in Csetjmp/longjmp

Page 47: Today… Project 1 (Shell) due today Homework #2 due Friday (January 30) Questions… BYU CS 345Threads1.

Project 2 - Tasking 47BYU CS 345

Creating a Task

int createTask( char* name, // task nameint (*task)(int, char**), // task addressint priority, // task priorityint argc, // task argument countchar* argv[ ]) // task argument pointers

{ int tid, j;for(tid=0; tid<MAX_TASKS; tid++){

if(tcb[tid].name[0] == 0) break; // find an open tcb entry slot}if(tid == MAX_TASKS) return -1; // too many tasksstrncpy(tcb[tid].name, name, MAX_NAME_SIZE-1); // task nametcb[tid].task = task; // task addresstcb[tid].state = S_NEW; // NEW task statetcb[tid].priority = priority; // task prioritytcb[tid].parent = curTask; // parent

tcb[tid].argc = argc; // argument count// ?? malloc new argv parameters (Project 1)tcb[tid].argv = argv; // argument pointers

createTask

Page 48: Today… Project 1 (Shell) due today Homework #2 due Friday (January 30) Questions… BYU CS 345Threads1.

Project 2 - Tasking 48BYU CS 345

Creating a Task (continued…)

tcb[tid].event = 0; // suspend semaphoretcb[tid].RPT = 0; // root page table (project 5)tcb[tid].cdir = cDir; // inherit parent cDir (project 6)// allocate own stack and stack pointertcb[tid].stack = malloc(STACK_SIZE * sizeof(int)); // signalstcb[tid].signal = 0; // Project 1if (tid){

tcb[tid].sigIntHandler = tcb[curTask].sigIntHandler; // SIGINT handler}else{

tcb[tid].sigIntHandler = defaultSigIntHandler; // default}

// ?? inserting task into "ready" queue (Project 2)

return tid; // return tcb index (curTask)} // end createTask

createTask

Page 49: Today… Project 1 (Shell) due today Homework #2 due Friday (January 30) Questions… BYU CS 345Threads1.

Project 2 - Tasking 49BYU CS 345

SWAP (Context Switch)

// ***********************************************************************// Do a context switch to next task.// 1. Save the state of the current task and enter kernel mode.// 2. Return from here when task is rescheduled.void swapTask(){

swapCount++; // increment swap cycle counter

if(setjmp(tcb[curTask].context)) return; // resume execution of task

// task context has been saved in tcb// if task RUNNING, set to READYif(tcb[curTask].state == S_RUNNING) tcb[curTask].state = S_READY;

longjmp(k_context, 2); // kernel context } // end swapTask

SWAP

Page 50: Today… Project 1 (Shell) due today Homework #2 due Friday (January 30) Questions… BYU CS 345Threads1.

Project 2 - Tasking 50BYU CS 345

Task Scheduling

// ***********************************************************************// schedulerint scheduler(){

int i, t, nextTask;if (numTasks == 0) return -1; // no task readynextTask = rq[0]; // take 1st (highest priority)for (i = 0; i < (numTasks-1); ++i) // roll to bottom of priority (RR){

if (tcb[rq[i]].priority > tcb[rq[i+1]].priority) break;t = rq[i];rq[i] = rq[i+1];rq[i+1] = t;

}return nextTask; // return task # to dispatcher

} // end scheduler

Scheduling

Page 51: Today… Project 1 (Shell) due today Homework #2 due Friday (January 30) Questions… BYU CS 345Threads1.

Project 2 - Tasking 51BYU CS 345

Task Dispatching

int dispatcher(int curTask){ int result;

switch(tcb[curTask].state) // schedule task{ case S_NEW: tcb[curTask].state = S_RUNNING; // set task to run state

if(setjmp(k_context)) break; // context switch to new tasktemp = (int*)tcb[curTask].stack + (STACK_SIZE-8);SET_STACK(temp) // move to new stackresult = (*tcb[curTask].task)(tcb[curTask].argument);tcb[curTask].state = S_EXIT; // set task to exit statelongjmp(k_context, 1); // return to kernel

case S_READY: tcb[curTask].state = S_RUNNING; // set task to run

case S_RUNNING: if(setjmp(k_context)) break; // return from taskif (signals()) break;longjmp(tcb[curTask].context, 3); // restore task context

case S_EXIT: if(curTask == 0) return -1; // if CLI, then quit schedulersyskillTask(curTask); // kill current task

case S_BLOCKED: break; // blocked / exit state}return 0;

} // end dispatcher

Project 2

Page 52: Today… Project 1 (Shell) due today Homework #2 due Friday (January 30) Questions… BYU CS 345Threads1.

Project 2 - Tasking 52BYU CS 345

Project 2 Grading Criteria

5 pts – Replace the simplistic 2-state scheduler with a 5-state, preemptive, prioritized, round-robin scheduler using ready and blocked task queues. (Be sure to handle the SIGSTOP signal.)

3 pts – Implement counting semaphores within the semSignal, semWait, and semTryLock functions. Add blocked queues to your semSignal and semWait semaphore functions. Validate that the SEM_SIGNAL /

SEM_WAIT / SEM_TRYLOCK binary and counting semaphore functions work properly with your scheduler.

2 pts – Modify the createTask( ) function to malloc argv arguments and insert the new task into the ready queue. Implement the killTask( ) function such that individual tasks can be terminated and resources recovered.

2 pts – Add a 10 second timer (tics10sec) counting semaphore to the polling routine (pollInterrupts). This can be done by including the <time.h>

header and calling the C function time(time_t *timer). semSignal the tics10sec semaphore every 10 seconds.

2 pts – Modify the list tasks command to display all tasks in the system queues in execution/priority order indicating the task name, if the

task is ready, paused, executing, or blocked, and the task priority. If the task is blocked, list the reason for the block.

1 pt – Create a reentrant high priority task that blocks (SEM_WAIT) on the 10 second timer semaphore (tics10sec). When activated, output a message with the current task number and time and then block

again.

Project 2

Page 53: Today… Project 1 (Shell) due today Homework #2 due Friday (January 30) Questions… BYU CS 345Threads1.

Project 2 - Tasking 53BYU CS 345

Project 2 Grading Criteria

5 pts – Upon entering main, schedule your CLI as task 0. Have the project2 command schedule timer tasks 1 through 9 and observe that they are functioning correctly. The “CLI” task blocks (SEM_WAIT) on the

binary semaphore inBufferReady, while the “TenSeconds” tasks block on the counting semaphore tics10sec. The “ImAlive” tasks do not

block but rather immediately swap (context switches) after incrementing their local counters. The high priority “Signal” tasks should respond immediately when semaphore signaled.

# Task Name Priority Time slice Blocking Semaphore

0 CLI w/pseudo-input interrupts 5 1 inBufferReady

1-9 TenSeconds 10 1 tics10sec

10 sTask1 20 1 sTask10

11 sTask2 20 1 sTask11

12 ImAlive 1 1 None

13 ImAlive 1 1 None

Project 2

Page 54: Today… Project 1 (Shell) due today Homework #2 due Friday (January 30) Questions… BYU CS 345Threads1.

Project 2 - Tasking 54BYU CS 345

Project 2 Grading Criteria

In addition to the possible 20 points, the following bonus/penalties apply:

+2 pts – bonus for early pass-off (at least one day before due date.)

+2 pts – for implementing buffered pseudo-interrupt driven character output and demonstrate that it works by implementing a my_printf function.

+1 pt – for implementing time slices that adjust task execution times when scheduled.

–2 pts – penalty for each school day late.

Project 2

Page 55: Today… Project 1 (Shell) due today Homework #2 due Friday (January 30) Questions… BYU CS 345Threads1.

Project 2 - Tasking 55BYU CS 345

Project 2 Bonus Points

Buffered pseudo-interrupt driven character output – my_printf

#include <stdarg.h>void my_printf(char* fmt, ...){

va_list arg_ptr;char pBuffer[128];char* s = pBuffer;

va_start(arg_ptr, fmt);vsprintf(pBuffer, fmt, arg_ptr);

while (*s) putchar(*s++);

va_end(arg_ptr);} // end my_printf

Project 2

Page 56: Today… Project 1 (Shell) due today Homework #2 due Friday (January 30) Questions… BYU CS 345Threads1.

Project 2 - Tasking 56BYU CS 345

Project 2 Bonus Points

Task time slices

// schedule shell taskcreateTask( "myShell", // task name

P1_shellTask, // task5, // task priority

argc, // task arg countargv // task argument pointers

);

4, // task time slice

Project 2

Page 57: Today… Project 1 (Shell) due today Homework #2 due Friday (January 30) Questions… BYU CS 345Threads1.

BYU CS 345 Project 2 - Tasking 57

Page 58: Today… Project 1 (Shell) due today Homework #2 due Friday (January 30) Questions… BYU CS 345Threads1.

Project 2 - Tasking 58BYU CS 345

STDARG - Variable Arguments Usage:

#include <stdarg.h>TYPE func(TYPE arg1,TYPE arg2, ...){ va_list ap; TYPE x; va_start(ap,arg2); x = va_arg(ap,TYPE); /* and so on */ va_end(ap);}

Project 2

Page 59: Today… Project 1 (Shell) due today Homework #2 due Friday (January 30) Questions… BYU CS 345Threads1.

Project 2 - Tasking 59BYU CS 345

VSPRINTF - Print Variable Arguments

Usage: #include <stdarg.h> #include <stdio.h> nout = vsprintf(str,format,varlist);

Description: "vsprintf" is the same as "sprintf" except that it prints out a number of

values from a variable argument list. The "varlist" variable must have been initialized with the "va_start" macro.

If there have already been calls to "va_arg" to obtain arguments from the variable list, "vsprintf" will start at the first argument that has not yet been obtained through "va_arg".

"vsprintf" effectively uses "va_arg" to obtain arguments from the variable list; therefore a call to "va_arg" after "vsprintf" will obtain the argument AFTER the last argument printed.

After a call to "vsprintf", the "varlist" variable should be assumed to be in an undefined state. If you want to use "varlist" again, you must call "va_end" to clean up, then "va_start" to reinitialize it.

Project 2

Page 60: Today… Project 1 (Shell) due today Homework #2 due Friday (January 30) Questions… BYU CS 345Threads1.

Project 2 - Tasking 60BYU CS 345

Page 61: Today… Project 1 (Shell) due today Homework #2 due Friday (January 30) Questions… BYU CS 345Threads1.

Project 2 - Tasking 61BYU CS 345

SWAP (Context Switch)

// ***********************************************************************// Do a context switch to next task.// Save the state of the current task and return to the kernel.// Return here when task is rescheduled.void swapTask(){ // increment swap cycle counter

swapCount++;// either capture state and enter kernel mode (k_context)// or resume execution by “return”ingif(setjmp(tcb[curTask].context)) return;// task context has been saved in tcb, set task state as “READY”if(tcb[curTask].state == S_RUNNING) tcb[curTask].state = S_READY;// enter kernel context and select highest priority ready tasklongjmp(k_context, 2);

} // end swapTask

Page 62: Today… Project 1 (Shell) due today Homework #2 due Friday (January 30) Questions… BYU CS 345Threads1.

Project 2 - Tasking 62BYU CS 345

STDARG - Variable Arguments Usage:

#include <stdarg.h>TYPE func(TYPE arg1,TYPE arg2, ...){ va_list ap; TYPE x; va_start(ap,arg2); x = va_arg(ap,TYPE); /* and so on */ va_end(ap);}

Description: The beginning of the function definition uses the normal format to declare arguments that are always

present. In addition, it uses an ellipsis (...) to stand for the variable part of the argument list. In its local declarations, the function should declare a variable of the type "va_list". This type is defined with a typedef statement in <stdarg.h>.

To begin processing the variable part of the argument list, you must issue the macro call va_start(ap,lastparm); where "ap" is the variable of type "va_list" and "lastparm" is the last named parameter (i.e. the one that immediately precedes the ellipsis).

To obtain an argument value from the variable part of the argument list, you use the macro call va_arg(ap,TYPE) where TYPE is the type of value that you want to obtain from the variable part of the argument list. The result of "va_arg" is an expression whose value is the next value from the argument list. For example, i = va_arg(ap,int); obtains an integer from the variable part of the argument list and assigns it to "i".

To finish processing the variable part of the argument list, you must issue the macro call va_end(ap); You can issue "va_end", even if you have not read every argument from the variable part of the list. After issuing "va_end", you can issue "va_start" again to go back to the beginning of the list and start over.

Page 63: Today… Project 1 (Shell) due today Homework #2 due Friday (January 30) Questions… BYU CS 345Threads1.

Project 2 - Tasking 63BYU CS 345

VSPRINTF - Print Variable Arguments

Usage: #include <stdarg.h> #include <stdio.h> nout = vsprintf(str,format,varlist);

Where: char *str;

points to the string where the output will be written. const char *format;

is a standard "printf" format string. va_list varlist;

is a variable argument list consisting of the values to be printed. int nout;

is the number of characters output (not counting the '\0' on the end of the string). If the print operation failed for some reason, a negative number is returned.

Description: "vsprintf" is the same as "sprintf" except that it prints out a number of values from a

variable argument list. The "varlist" variable must have been initialized with the "va_start" macro. If there have already been calls to "va_arg" to obtain arguments from the variable list, "vsprintf" will start at the first argument that has not yet been obtained through "va_arg". "vsprintf" effectively uses "va_arg" to obtain arguments from the variable list; therefore a call to "va_arg" after "vsprintf" will obtain the argument AFTER the last argument printed.

After a call to "vsprintf", the "varlist" variable should be assumed to be in an undefined state. If you want to use "varlist" again, you must call "va_end" to clean up, then "va_start" to reinitialize it.

Page 64: Today… Project 1 (Shell) due today Homework #2 due Friday (January 30) Questions… BYU CS 345Threads1.

Project 2 - Tasking 64BYU CS 345

Task Dispatching

int dispatcher(int curTask){ int result;

switch(tcb[curTask].state) // schedule task{ case S_NEW: // new task, start executing

tcb[curTask].state = S_RUNNING; // set task to run stateif(setjmp(k_context)) break; // context switch to new tasktemp = (int*)tcb[curTask].stack + (STACK_SIZE-8); // move to new stackSET_STACK(temp)result = (*tcb[curTask].task)(tcb[curTask].argument); // begin execution of tasktcb[curTask].state = S_EXIT; // set task to exit statelongjmp(k_context, 1); // return to kernel

case S_READY: tcb[curTask].state = S_RUNNING; // set task to run

case S_RUNNING: if(setjmp(k_context)) break; // return from taskif (signals()) break;longjmp(tcb[curTask].context, 3); // restore task context

case S_BLOCKED: break; // ?? Could check here to unblock task

case S_EXIT: if(curTask == 0) return -1; // if CLI, then quit schedulersyskillTask(curTask); // kill current taskbreak;

default: powerDown(-1); // problem!!}return 0;

} // end dispatcher

Calls to Signal handlers inserted here…

Lab 2

Page 65: Today… Project 1 (Shell) due today Homework #2 due Friday (January 30) Questions… BYU CS 345Threads1.

Project 2 - Tasking 65BYU CS 345

Task Dispatching

int dispatcher(int curTask){ int result;

switch(tcb[curTask].state) // schedule task{

case S_NEW: tcb[curTask].state = S_RUNNING; // set task to run stateif(setjmp(k_context)) break; // context switch to new tasktemp = (int*)tcb[curTask].stack + (STACK_SIZE-8);SET_STACK(temp) // move to new stackresult = (*tcb[curTask].task)(tcb[curTask].argument);tcb[curTask].state = S_EXIT; // set task to exit statelongjmp(k_context, 1); // return to kernel

case S_READY: tcb[curTask].state = S_RUNNING; // set task to run

case S_RUNNING: if(setjmp(k_context)) break; // return from taskif (signals()) break;longjmp(tcb[curTask].context, 3); // restore task context

case S_EXIT: if(curTask == 0) return -1; // if CLI, then quit schedulersyskillTask(curTask); // kill current taskbreak;

default: powerDown(-1); // problem!!case S_BLOCKED: break; // NEVER HAPPEN!

}return 0;

} // end dispatcher

Lab 2

Page 66: Today… Project 1 (Shell) due today Homework #2 due Friday (January 30) Questions… BYU CS 345Threads1.

Project 2 - Tasking 66

Step 1: Priority Queue

Create a priority queue typedef int TID; // task ID

typedel int Priority; // task prioritytypedef int* PQueue; // priority queue

Write queue functions to add/delete elements int enQ(PQueue q, TID tid, Priority p); int deQ(PQueue q, TID tid);

q # | pr1/tid1 | pr2/tid2 | … tid >=0 find and delete tid from q

-1 return highest priority tid int tid (if found and deleted from q)

-1 (if q empty or task not found)

BYU CS 345

Priority/TID

Priority/TID

Priority/TID

Priority/TID

# of entries

typedef struct{ int size;

union{ int element;

struct{ uint8 tid;

uint8 priority;} entry;

} queue[100];} PQueue;

Page 67: Today… Project 1 (Shell) due today Homework #2 due Friday (January 30) Questions… BYU CS 345Threads1.

BYU CS 345 Project 2 - Tasking 67

Page 68: Today… Project 1 (Shell) due today Homework #2 due Friday (January 30) Questions… BYU CS 345Threads1.

Project 2 - Tasking 68BYU CS 345

Project 2

Change the scheduler from a 2 state to a 5 state scheduler using semaphores with priority queues.

int scheduler() in os345.c semWait(), semSignal, semTryLock in os345semaphores.c

Tasks are functions and are added to the task scheduler ready queue via the “createTask()” function.

The first task scheduled is your shell from Project 1. The “SWAP” directive replaces clock interrupts for context

switching between tasks (cooperative scheduling). Context switching directives may be placed anywhere in

your user task code. SWAP, SEM_SIGNAL, SEM_WAIT, SEM_TRYLOCK

P2 - Tasking

Page 69: Today… Project 1 (Shell) due today Homework #2 due Friday (January 30) Questions… BYU CS 345Threads1.

Project 2 - Tasking 69BYU CS 345

Project 2 (continued…)

The highest priority, unblocked, ready task should always be executing.

Tasks of the same priority should be scheduled in a round-robin, FIFO fashion.

Any change of events (SEM_SIGNAL) should cause a context switch.

To simulate interrupts, character inputs and timers need to be “polled” in the scheduling loop.

void pollInterrupts() in OS345p1.c Parsed command line arguments are passed to tasks (ie.

functions) via argc/argv variables.

P2 - Tasking

Page 70: Today… Project 1 (Shell) due today Homework #2 due Friday (January 30) Questions… BYU CS 345Threads1.

Project 2 - Tasking 70

Step 1: Priority Queue

Create a priority queue typedef int TID; // task ID

typedel int Priority; // task prioritytypedef int* PQueue; // priority queue

PQueue rq; // ready queuerq = (int*)malloc(MAX_TASKS * sizeof(int));rq[0] = 0; // init ready queue

Queue functions int enQ(PQueue q, TID tid, Priority p); int deQ(PQueue q, TID tid);

q # | pr1/tid1 | pr2/tid2 | … tid >=0 find and delete tid from q

-1 return highest priority tid int tid (if found and deleted from q)

-1 (if q empty or task not found)

BYU CS 345

Priority/TID

Priority/TID

Priority/TID

Priority/TID

# of entries

rq[5]

rq[4] 10 / 3

rq[3] 5 / 2

rq[2] 5 / 0

rq[1] 2 / 1

rq[0] 4

Project 2 Assignment

Page 71: Today… Project 1 (Shell) due today Homework #2 due Friday (January 30) Questions… BYU CS 345Threads1.

Project 2 - Tasking 71BYU CS 345

State Change in C

The setjmp/longjmp set of macros implemented in the C provide the perfect platform to perform complex flow-control.

The setjmp function saves the state of a program. The state of a program, to be precise, are the values of sp (stack pointer), fp (frame pointer), pc (program counter).

A program state is completely defined by this set of registers and the contents of the memory, which includes the stack.

Executing a setjmp returns 0 after saving the stack environment.

If setjmp returns as a result of a longjmp call, the value is the argument of the longjmp (0 is never returned).

A call to longjmp restores the saved environment and returns control to the point just after the corresponding setjmp call.

C Threads

Page 72: Today… Project 1 (Shell) due today Homework #2 due Friday (January 30) Questions… BYU CS 345Threads1.

Project 2 - Tasking 72

Step 2: Schedule w/Ready Queue

Create a ready priority queue PQueue rq; // ready queue

rq = (int*)malloc(MAX_TASKS * sizeof(int));rq[0] = 0; // init ready queue

Add new task to ready queue in createTask enQ(rq, tid, tcb[tid].priority);

Change scheduler() to deQueue and then enQueue next task

if ((nextTask = deQ(rq, -1)) >= 0){

enQ(rq, nextTask);}

BYU CS 345

Priority/TID

Priority/TID

Priority/TID

Priority/TID

# of entries

rq[5]

rq[4] 10 / 3

rq[3] 5 / 2

rq[2] 5 / 0

rq[1] 2 / 1

rq[0] 4

Project 2 Assignment

Page 73: Today… Project 1 (Shell) due today Homework #2 due Friday (January 30) Questions… BYU CS 345Threads1.

Project 2 - Tasking 73

Step 3: 5-State Scheduling

BYU CS 345

Add priority queue to semaphore struct typedef struct semaphore // semaphore

{ struct semaphore* semLink; // link to next semaphorechar* name; // semaphore name (malloc)

int state; // state (count)int type; // type (binary/counting)int taskNum; // tid of creatorPQueue q; // blocked queue

} Semaphore;

Malloc semaphore queue in createSemaphore semaphore->q = (int*)malloc(MAX_TASKS * sizeof(int));

semaphore->q[0] = 0; // init queue

semWait: deQueue current task from ready queue and enQueue in semaphore queue

semSignal: deQueue task from blocked queue and enQueue in ready queue.

Project 2 Assignment

Page 74: Today… Project 1 (Shell) due today Homework #2 due Friday (January 30) Questions… BYU CS 345Threads1.

Project 2 - Tasking 74

Step 4a: Counting Semaphore

BYU CS 345

Add counting functionality to semaphores os345semaphores.c: semSignal, semWait, semTryLock Replace goto temp;

Add a 10 second timer (tics10sec) counting semaphore to the polling routine (os345interrupts.c).

#include <time.h> header. Call the C function time(time_t *timer). semSignal the tics10sec semaphore every 10 seconds.

Create a reentrant high priority timing task that blocks (SEM_WAIT) on the 10 second timer semaphore

(tics10sec). when activated, outputs a message with the current task

number and time and then blocks again.

Project 2 Assignment

Page 75: Today… Project 1 (Shell) due today Homework #2 due Friday (January 30) Questions… BYU CS 345Threads1.

Project 2 - Tasking 75

Step 4b: List Tasks

BYU CS 345

Modify the list tasks command to Display all tasks in all system queues in execution/priority

order List task name, if the task is ready, paused, executing, or

blocked, and the task priority. If the task is blocked, list the reason for the block.

Use the project2 command to schedule timer tasks 1 through 9, 2 signal tasks and 2 “ImAlive” tasks.

The tics10sec task about the current time every 10 seconds in a round robin order. (Round Robin)

The “ImAlive” tasks will periodically say hello. (Blocking) The high priority “Signal” tasks should respond immediately

when semaphore signaled. (Priority)

Project 2 Assignment

Page 76: Today… Project 1 (Shell) due today Homework #2 due Friday (January 30) Questions… BYU CS 345Threads1.

Project 2 - Tasking 76

Step 4c: Verification

BYU CS 345

Demo

# Task Name Priority Time slice Blocking Semaphore

0 CLI w/pseudo-input interrupts 5 1 inBufferReady

1-9 TenSeconds 10 1 tics10sec

10 sTask1 20 1 sTask10

11 sTask2 20 1 sTask11

12 ImAlive 1 1 None

13 ImAlive 1 1 None

Project 2 Assignment

Page 77: Today… Project 1 (Shell) due today Homework #2 due Friday (January 30) Questions… BYU CS 345Threads1.

Project 2 - Tasking 77

Step 5: Bonus Credit

BYU CS 345

Implement a buffered pseudo-interrupt driven character output and demonstrate that it works by implementing a my_printf function.

Implement time slices that adjust task execution times when scheduled.

createTask( "myShell", // task nameP1_shellTask, // task5, // task priorityargc, // task arg countargv // task argument pointers

);

#include <stdarg.h>void my_printf(char* fmt, ...){ va_list arg_ptr;

char pBuffer[128];char* s = pBuffer;va_start(arg_ptr, fmt);vsprintf(pBuffer, fmt, arg_ptr);while (*s) putIObuffer(*s++);va_end(arg_ptr);

} // end my_printf

P2 - Tasking

Page 78: Today… Project 1 (Shell) due today Homework #2 due Friday (January 30) Questions… BYU CS 345Threads1.

BYU CS 345 Project 2 - Tasking 78

Page 79: Today… Project 1 (Shell) due today Homework #2 due Friday (January 30) Questions… BYU CS 345Threads1.

Threads 79

Project 2 – Tasking (Step 1)

Create a priority ready queue typedef int* PQueue; // priority queue PQueue rq = (int*)malloc(MAX_TASKS * sizeof(int));

rq[0] = 0; // init ready queue Create enQ and deQ functions:

int enQ(PQueue q, TID tid); int deQ(PQueue q, TID tid);

q # | tid1 | tid2 | … Add new tasks to the ready queue in createTask()

tid = enQ(rq, tid)); // add task to ready queue Change scheduler() to use a priority queue:

if ((nextTask = deQ(rq, -1)) >= 0) enQ(rq, nextTask);

BYU CS 345

Page 80: Today… Project 1 (Shell) due today Homework #2 due Friday (January 30) Questions… BYU CS 345Threads1.

Threads 80

Project 2 – Tasking (Step 2)

Add a priority ready queue to semaphores: typedef int* PQueue; // priority queue PQueue rq = (int*)malloc(MAX_TASKS * sizeof(int));

rq[0] = 0; // init ready queue Move blocking tasks from ready to blocked queue:

int enQ(PQueue q, TID tid); int deQ(PQueue q, TID tid);

q # | tid1 | tid2 | …

BYU CS 345

Page 81: Today… Project 1 (Shell) due today Homework #2 due Friday (January 30) Questions… BYU CS 345Threads1.

Project 2 - Tasking 81BYU CS 345

Task Scheduling

Ready Priority Queue

Semaphore Priority Queue

Semaphore Priority Queue

Semaphore Priority Queue

SWAP

SEM_SIGNAL SEM_WAIT

SEM_SIGNAL SEM_WAIT

SEM_SIGNAL SEM_WAIT

Executing

Scheduler / Dispatcher

Scheduling

Page 82: Today… Project 1 (Shell) due today Homework #2 due Friday (January 30) Questions… BYU CS 345Threads1.

Threads 82BYU CS 345

State Change in C

The setjmp/longjmp set of macros implemented in the C provide the perfect platform to perform complex flow-control.

The setjmp function saves the state of a program. The state of a program, to be precise, are the values of sp (stack pointer), fp (frame pointer), pc (program counter).

A program state is completely defined by this set of registers and the contents of the memory, which includes the stack.

Executing a setjmp returns 0 after saving the stack environment.

If setjmp returns as a result of a longjmp call, the value is the argument of the longjmp (0 is never returned).

A call to longjmp restores the saved environment and returns control to the point just after the corresponding setjmp call.

C Threads

Page 83: Today… Project 1 (Shell) due today Homework #2 due Friday (January 30) Questions… BYU CS 345Threads1.

Project 2 - Tasking 83BYU CS 345

setjmp / longjmp

#include <setjmp.h> jmp_buf struct

stack pointer (sp), frame pointer (fp), and program counter (pc).

setjmp(jmp_buf env); saves the program state (sp, fp, pc) in env so that

longjmp() can restore them later. returns 0 value.

longjmp(jmp_buf env, int val); resets the registers to the values saved in env. longjmp() returns as if you have just called the

setjmp() call that saved env with non-zero value.

setjmp/longjmp

Page 84: Today… Project 1 (Shell) due today Homework #2 due Friday (January 30) Questions… BYU CS 345Threads1.

Project 2 - Tasking 84BYU CS 345

Multi-threading in Csetjmp/longjmp

// new threadsfor (tid = 0; tid < 4; tid++){ if (setjmp(k_context) == 0) { temp = (int*)tcb[tid].stackEnd; SET_STACK(temp); if (setjmp(tcb[tid].context) == 0) { longjmp(k_context, 1); } myThread(); }}

// schedule threadswhile (1){ tid = scheduler(); if (setjmp(k_context) == 0) { longjmp(tcb[tid].context, 3); }}

jmp_buf k_context;int tid;

// my threadvoid myThread(){ while (1) { if(!setjmp(tcb[tid].context)) longjmp(k_context,2);

// execute function }}

Page 85: Today… Project 1 (Shell) due today Homework #2 due Friday (January 30) Questions… BYU CS 345Threads1.

Project 2 - Tasking 85BYU CS 345

Multi-tasking in Csetjmp/longjmp

Page 86: Today… Project 1 (Shell) due today Homework #2 due Friday (January 30) Questions… BYU CS 345Threads1.

BYU CS 345 Project 2 - Tasking 86

Page 87: Today… Project 1 (Shell) due today Homework #2 due Friday (January 30) Questions… BYU CS 345Threads1.

Project 2 - Tasking 87BYU CS 345

Multi-tasking in Csetjmp/longjmp

for (tid = 0; tid < 4; tid++){ if (setjmp(k_context) == 0) { temp = (int*)tcb[tid].stackEnd; SET_STACK(temp); if (setjmp(tcb[tid].context) == 0) { longjmp(k_context, 1); } myFunc(); }}

while (1){ tid = scheduler(); if (setjmp(k_context) == 0) { longjmp(tcb[tid].context, 3); }}

jmp_buf k_context;int tid;

#define SWAP \ if(!setjmp(tcb[tid].context)) \ longjmp(k_context,2);

void myFunc(){ while (1) { SWAP; if(!setjmp(tcb[tid].context)) longjmp(k_context,2);

// execute function }}

Page 88: Today… Project 1 (Shell) due today Homework #2 due Friday (January 30) Questions… BYU CS 345Threads1.

Project 2 - Tasking 88

Step 1: Priority Queue

Create a priority queue typedef int TID; // task ID

typedef int Priority; // task prioritytypedef int* PQueue; // priority queue

PQueue rq; // ready queuerq = (int*)malloc(MAX_TASKS * sizeof(int));rq[0] = 0; // init ready queue

Queue functions int enQ(PQueue q, TID tid, Priority p); int deQ(PQueue q, TID tid);

q # | pr1/tid1 | pr2/tid2 | … tid >=0 find and delete tid from q

-1 return highest priority tid int tid (if found and deleted from q)

-1 (if q empty or task not found)

BYU CS 345

Priority/TID

Priority/TID

Priority/TID

Priority/TID

# of entries

rq[5]

rq[4] 10 / 3

rq[3] 5 / 2

rq[2] 5 / 0

rq[1] 2 / 1

rq[0] 4

P2 - Tasking


Recommended