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

Slides:



Advertisements
Similar presentations
Processes and Threads Chapter 3 and 4 Operating Systems: Internals and Design Principles, 6/E William Stallings Patricia Roy Manatee Community College,
Advertisements

Threads, SMP, and Microkernels
More on Processes Chapter 3. Process image _the physical representation of a process in the OS _an address space consisting of code, data and stack segments.
Chapter 3 Process Description and Control
Project 2 - Tasking.
Project 1 – My Shell Let’s get started… Alex Milenkovich.
Threads, SMP, and Microkernels Chapter 4. Process Resource ownership - process is allocated a virtual address space to hold the process image Scheduling/execution-
Chapter 4 Threads, SMP, and Microkernels Patricia Roy Manatee Community College, Venice, FL ©2008, Prentice Hall Operating Systems: Internals and Design.
Computer Systems/Operating Systems - Class 8
Day 10 Threads. Threads and Processes  Process is seen as two entities Unit of resource allocation (process or task) Unit of dispatch or scheduling (thread.
Threads Irfan Khan Myo Thein What Are Threads ? a light, fine, string like length of material made up of two or more fibers or strands of spun cotton,
Chapter 5 Processes and Threads Copyright © 2008.
Processes CSCI 444/544 Operating Systems Fall 2008.
Introduction to Operating Systems – Windows process and thread management In this lecture we will cover Threads and processes in Windows Thread priority.
Threads 1 CS502 Spring 2006 Threads CS-502 Spring 2006.
3.5 Interprocess Communication
CS-502 Fall 2006Processes in Unix, Linux, & Windows 1 Processes in Unix, Linux, and Windows CS502 Operating Systems.
CSSE Operating Systems
1 Chapter 4 Threads Threads: Resource ownership and execution.
Threads, SMP, and Microkernels
Threads. Processes and Threads  Two characteristics of “processes” as considered so far: Unit of resource allocation Unit of dispatch  Characteristics.
BYU CS 345Chapter 3 - Processes1 Today… Lab 1 due tomorrow Early pass-off today Finish up with Implement the following shell commands: Add – add all numbers.
1 Process Description and Control Chapter 3 = Why process? = What is a process? = How to represent processes? = How to control processes?
A. Frank - P. Weisberg Operating Systems Introduction to Tasks/Threads.
Threads CS 416: Operating Systems Design, Spring 2001 Department of Computer Science Rutgers University
Process Description and Control A process is sometimes called a task, it is a program in execution.
1 Threads Chapter 4 Reading: 4.1,4.4, Process Characteristics l Unit of resource ownership - process is allocated: n a virtual address space to.
Processes in Unix, Linux, and Windows CS-502 Fall Processes in Unix, Linux, and Windows CS502 Operating Systems (Slides include materials from Operating.
Chapter 5 Concurrency: Mutual Exclusion and Synchronization.
Chapter 51 Threads Chapter 5. 2 Process Characteristics  Concept of Process has two facets.  A Process is: A Unit of resource ownership:  a virtual.
CSE 451: Operating Systems Autumn 2013 Module 6 Review of Processes, Kernel Threads, User-Level Threads Ed Lazowska 570 Allen.
Operating Systems CSE 411 CPU Management Sept Lecture 11 Instructor: Bhuvan Urgaonkar.
Chapter 4 Threads, SMP, and Microkernels Dave Bremer Otago Polytechnic, N.Z. ©2008, Prentice Hall Operating Systems: Internals and Design Principles, 6/E.
Operating Systems Lecture 09: Threads (Chapter 4)
Thread. A basic unit of CPU utilization. It comprises a thread ID, a program counter, a register set, and a stack. It is a single sequential flow of control.
Chapter 4: Threads. 4.2CSCI 380 Operating Systems Chapter 4: Threads Overview Multithreading Models Threading Issues Pthreads Windows XP Threads Linux.
1 Lecture 4: Threads Operating System Fall Contents Overview: Processes & Threads Benefits of Threads Thread State and Operations User Thread.
Chapter 4 Threads, SMP, and Microkernels Patricia Roy Manatee Community College, Venice, FL ©2008, Prentice Hall Operating Systems: Internals and Design.
Chapter 41 Processes Chapter 4. 2 Processes  Multiprogramming operating systems are built around the concept of process (also called task).  A process.
Processes and Threads Processes have two characteristics: – Resource ownership - process includes a virtual address space to hold the process image – Scheduling/execution.
Lecture 3 Process Concepts. What is a Process? A process is the dynamic execution context of an executing program. Several processes may run concurrently,
CE Operating Systems Lecture 11 Windows – Object manager and process management.
Threads, SMP, and Microkernels Chapter 4. Process Resource ownership - process is allocated a virtual address space to hold the process image Scheduling/execution-
Threads G.Anuradha (Reference : William Stallings)
1 Threads, SMP, and Microkernels Chapter 4. 2 Process Resource ownership: process includes a virtual address space to hold the process image (fig 3.16)
1 Threads, SMP, and Microkernels Chapter Multithreading Operating system supports multiple threads of execution within a single process MS-DOS.
1 Lecture 4: Threads Advanced Operating System Fall 2010.
Lecture 5: Threads process as a unit of scheduling and a unit of resource allocation processes vs. threads what to program with threads why use threads.
Operating Systems CSE 411 CPU Management Sept Lecture 10 Instructor: Bhuvan Urgaonkar.
Lab 1 due Thursday Early pass-off Wednesday Finish up with Implement the following shell commands: Add – add all numbers in command line (decimal or hexadecimal).
Department of Computer Science and Software Engineering
Processes, Threads, and Process States. Programs and Processes  Program: an executable file (before/after compilation)  Process: an instance of a program.
Operating Systems: Internals and Design Principles
© Janice Regan, CMPT 300, May CMPT 300 Introduction to Operating Systems Operating Systems Processes and Threads.
Module 2.0: Threads.
Processes & Threads Introduction to Operating Systems: Module 5.
Threads-Process Interaction. CONTENTS  Threads  Process interaction.
Processes and Threads Chapter 4.
Threads. Thread A basic unit of CPU utilization. An Abstract data type representing an independent flow of control within a process A traditional (or.
Chapter 4 Threads, SMP, and Microkernels Dave Bremer Otago Polytechnic, N.Z. ©2008, Prentice Hall Operating Systems: Internals and Design Principles, 6/E.
1 Threads, SMP, and Microkernels Chapter 4. 2 Process Resource ownership - process includes a virtual address space to hold the process image Scheduling/execution-
Processes and Threads Chapter 3 and 4 Operating Systems: Internals and Design Principles, 6/E William Stallings Patricia Roy Manatee Community College,
Processes and threads.
Process concept.
Chapter 3: Process Concept
CS 6560: Operating Systems Design
Chapter 2 Processes and Threads Today 2.1 Processes 2.2 Threads
CSE 451: Operating Systems Spring 2012 Module 6 Review of Processes, Kernel Threads, User-Level Threads Ed Lazowska 570 Allen.
Threads Chapter 4.
CS510 Operating System Foundations
Presentation transcript:

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

BYU CS 345Chapter 3 - Processes2 7. Operating System Control Tables Control Tables Task Control Block

BYU CS 345Chapter 3 - Processes3 Task Control Block (tcb) P2 - Tasking // task control block typedef struct// task control block {char* name;// task name int (*task)(int,char**);// task address int state;// task state 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 (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 parent int 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;

Processes and Threads Chapter 4

BYU CS 345Threads5 CS 345 Stalling’s Chapter#Project 1: Computer System Overview 2: Operating System Overview 4P1: Shell 3: Process Description and Control 4: Threads 4P2: Tasking 5: Concurrency: ME and Synchronization 6: Concurrency: Deadlock and Starvation 6P3: Jurassic Park 7: Memory Management 8: Virtual memory 6P4: Virtual Memory 9: Uniprocessor Scheduling 10: Multiprocessor and Real-Time Scheduling 6P5: Scheduling 11: I/O Management and Disk Scheduling 12: File Management 8P6: FAT Student Presentations6

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 345Threads6

BYU CS 345Threads7 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?

BYU CS 345Threads8 What is moving around?

BYU CS 345Threads9 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

BYU CS 345Threads10 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

BYU CS 345Threads11 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

BYU CS 345Threads12 Threads and Processes one process one thread multiple processes one thread per process multiple processes multiple threads per process one process multiple threads Threads

BYU CS 345Threads13 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

BYU CS 345Threads14 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

BYU CS 345Threads15 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

BYU CS 345Threads16 Multi-threaded Process Threads

BYU CS 345Threads17 Exclusive/Shared Resources Thread Control Block User Stack User Stack Kernel Stack Kernel Stack User Address Space User Address Space Process Control Block Process Control Block Thread Single-Threaded Process Model Multithreaded Process Model Thread Control Block User Stack Kernel Stack Thread Control Block User Stack Kernel Stack Thread Threads

BYU CS 345Threads18 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

BYU CS 345Threads19 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

BYU CS 345Threads20 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.”inter- process communicationcomputer programsubroutineaddress space 1. Client calls the client stub (stack).stub 2. Client stub packs (marshalls) parameters.Client stub 3. Client's OS sends message to server. 4. Server OS passes packets to server stub.server stub 5. Server stub unpacks (unmarshalls) message. 6. Server stub calls the server procedure. 7. Reply traces in the reverse direction.

BYU CS 345Threads21 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

BYU CS 345Threads22 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

BYU CS 345Threads23 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

BYU CS 345Threads24 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

BYU CS 345Threads25 User-Level and Kernel-Level Threads Thread Management

BYU CS 345Threads26 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

BYU CS 345Threads27 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).

BYU CS 345Threads28 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.

BYU CS 345Threads29 Thread Support As of , Linux has supported kernel-level multithreading. User-level thread libraries around as early as 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).

BYU CS 345Threads30 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

Project 2 - Tasking

BYU CS 345Project 2 - Tasking32 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

BYU CS 345Project 2 - Tasking33 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

Step 1: Priority Queue Create a priority queue typedef int TID;// task ID typedef int Priority;// task priority typedef int* PQueue;// priority queue PQueue rq;// ready queue rq = (int*)malloc(MAX_TASKS * sizeof(int)); rq[0] = 0;// init ready queue Queue functions int enQ(PQueue q, TID tid, Priority p); qpriority queue (# | pr1/tid1 | pr2/tid2 | …) tidtask id ptask priority intreturn tid int deQ(PQueue q, TID tid); qpriority queue tidfind and delete tid from q (tid == -1  find/delete highest priority) intdeleted tid (tid == -1  q empty or task not found) BYU CS 345Project 2 - Tasking34  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

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 345Project 2 - Tasking35  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

2-State Scheduler BYU CS 345Project 2 - Tasking36 createTask() dispatch() swapTask() killTask() New Ready Queue RunningExit P2 - Tasking nextTask = enQueue(rq, deQueue(rq, -1));

Step 3: 5-State Scheduling BYU CS 345 Add priority queue to semaphore struct typedef struct semaphore// semaphore {struct semaphore* semLink;// link to next semaphore char* name;// semaphore name (malloc) int state;// state (count) int type;// type (binary/counting) int taskNum;// tid of creator PQueue 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 - Tasking37 P2 - Tasking

Blocked Queues semWait() semTryLock() semSignal() 5-State Scheduler BYU CS 345Project 2 - Tasking38 createTask() dispatch() swapTask() killTask() New Ready Queue RunningExit #define SWAP swapTask(); #define SEM_WAIT(s) semWait(s); #define SEM_SIGNAL(s) semSignal(s); #define SEM_TRYLOCK(s) semTryLock(s); P2 - Tasking

BYU CS 345Project 2 - Tasking39 Task Scheduling Ready Priority Queue Semaphore Priority Queue … SWAP SEM_SIGNALSEM_WAIT SEM_SIGNALSEM_WAIT SEM_SIGNALSEM_WAIT Executing Scheduler / Dispatcher Scheduling

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 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. Project 2 - Tasking40 P2 - Tasking

BYU CS 345Project 2 - Tasking41 Task Control Block (tcb) P2 - Tasking // task control block typedef struct// task control block { char* name;// task name int (*task)(int,char**);// task address int 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 parent int 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.

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. Project 2 - Tasking42 P2 - Tasking

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. Project 2 - Tasking43 #Task NamePriorityTime sliceBlocking Semaphore 0CLI w/pseudo-input interrupts51 inBufferReady 1-9TenSeconds101 tics10sec 10sTask1201 sTask10 11sTask2201 sTask11 12ImAlive11None 13ImAlive11None P2 - Tasking

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. Project 2 - Tasking44 createTask("myShell",// task name P1_shellTask,// task 5,// task priority argc,// task arg count argv// task argument pointers ); #include 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

BYU CS 345Project 2 - Tasking45 setjmp / longjmp #include 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

BYU CS 345Project 2 - Tasking46 Multi-tasking in C setjmp/longjmp

BYU CS 345Project 2 - Tasking47 Creating a Task int createTask(char* name,// task name int (*task)(int, char**),// task address int priority,// task priority int argc,// task argument count char* 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 tasks strncpy(tcb[tid].name, name, MAX_NAME_SIZE-1);// task name tcb[tid].task = task;// task address tcb[tid].state = S_NEW;// NEW task state tcb[tid].priority = priority;// task priority tcb[tid].parent = curTask;// parent tcb[tid].argc = argc;// argument count // ?? malloc new argv parameters (Project 1) tcb[tid].argv = argv;// argument pointers createTask

BYU CS 345Project 2 - Tasking48 Creating a Task (continued…) tcb[tid].event = 0;// suspend semaphore tcb[tid].RPT = 0;// root page table (project 5) tcb[tid].cdir = cDir;// inherit parent cDir (project 6) // allocate own stack and stack pointer tcb[tid].stack = malloc(STACK_SIZE * sizeof(int)); // signals tcb[tid].signal = 0;// Project 1 if (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

BYU CS 345Project 2 - Tasking49 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 READY if(tcb[curTask].state == S_RUNNING) tcb[curTask].state = S_READY; longjmp(k_context, 2); // kernel context } // end swapTask SWAP

BYU CS 345Project 2 - Tasking50 Task Scheduling // *********************************************************************** // scheduler int scheduler() { int i, t, nextTask; if (numTasks == 0) return -1;// no task ready nextTask = rq[0];// take 1 st (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

BYU CS 345Project 2 - Tasking51 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 task temp = (int*)tcb[curTask].stack + (STACK_SIZE-8); SET_STACK(temp) // move to new stack result = (*tcb[curTask].task)(tcb[curTask].argument); tcb[curTask].state = S_EXIT;// set task to exit state longjmp(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 task if (signals()) break; longjmp(tcb[curTask].context, 3); // restore task context case S_EXIT:if(curTask == 0) return -1;// if CLI, then quit scheduler syskillTask(curTask);// kill current task case S_BLOCKED:break; // blocked / exit state } return 0; } // end dispatcher Project 2

BYU CS 345Project 2 - Tasking52 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 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

BYU CS 345Project 2 - Tasking53 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 NamePriorityTime sliceBlocking Semaphore 0CLI w/pseudo-input interrupts51 inBufferReady 1-9TenSeconds101 tics10sec 10sTask1201 sTask10 11sTask2201 sTask11 12ImAlive11None 13ImAlive11None Project 2

BYU CS 345Project 2 - Tasking54 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

BYU CS 345Project 2 - Tasking55 Project 2 Bonus Points Buffered pseudo-interrupt driven character output – my_printf #include 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

BYU CS 345Project 2 - Tasking56 Project 2 Bonus Points Task time slices // schedule shell task createTask("myShell",// task name P1_shellTask,// task 5,// task priority argc,// task arg count argv// task argument pointers ); 4,// task time slice Project 2

BYU CS 345Project 2 - Tasking57

BYU CS 345Project 2 - Tasking58 STDARG - Variable Arguments Usage: #include 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

BYU CS 345Project 2 - Tasking59 VSPRINTF - Print Variable Arguments Usage: #include 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

BYU CS 345Project 2 - Tasking60

BYU CS 345Project 2 - Tasking61 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”ing if(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 task longjmp(k_context, 2); } // end swapTask

BYU CS 345Project 2 - Tasking62 STDARG - Variable Arguments Usage: #include 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. 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.

BYU CS 345Project 2 - Tasking63 VSPRINTF - Print Variable Arguments Usage: #include 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.

BYU CS 345Project 2 - Tasking64 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 state if(setjmp(k_context)) break;// context switch to new task temp = (int*)tcb[curTask].stack + (STACK_SIZE-8);// move to new stack SET_STACK(temp) result = (*tcb[curTask].task)(tcb[curTask].argument);// begin execution of task tcb[curTask].state = S_EXIT;// set task to exit state longjmp(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 task if (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 scheduler syskillTask(curTask);// kill current task break; default: powerDown(-1);// problem!! } return 0; } // end dispatcher Calls to Signal handlers inserted here… Lab 2

BYU CS 345Project 2 - Tasking65 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 task temp = (int*)tcb[curTask].stack + (STACK_SIZE-8); SET_STACK(temp) // move to new stack result = (*tcb[curTask].task)(tcb[curTask].argument); tcb[curTask].state = S_EXIT;// set task to exit state longjmp(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 task if (signals()) break; longjmp(tcb[curTask].context, 3); // restore task context case S_EXIT:if(curTask == 0) return -1;// if CLI, then quit scheduler syskillTask(curTask);// kill current task break; default: powerDown(-1);// problem!! case S_BLOCKED:break;// NEVER HAPPEN! } return 0; } // end dispatcher Lab 2

Step 1: Priority Queue Create a priority queue typedef int TID;// task ID typedel int Priority;// task priority typedef 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>=0find and delete tid from q -1return highest priority tid inttid(if found and deleted from q) -1(if q empty or task not found) BYU CS 345Project 2 - Tasking66  Priority/TID # of entries typedef struct {int size; union {int element; struct {uint8 tid; uint8 priority; } entry; } queue[100]; } PQueue;

BYU CS 345Project 2 - Tasking67

BYU CS 345Project 2 - Tasking68 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

BYU CS 345Project 2 - Tasking69 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

Step 1: Priority Queue Create a priority queue typedef int TID;// task ID typedel int Priority;// task priority typedef int* PQueue;// priority queue PQueue rq;// ready queue rq = (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>=0find and delete tid from q -1return highest priority tid inttid(if found and deleted from q) -1(if q empty or task not found) BYU CS 345Project 2 - Tasking70  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

BYU CS 345Project 2 - Tasking71 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

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 345Project 2 - Tasking72  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

Step 3: 5-State Scheduling BYU CS 345 Add priority queue to semaphore struct typedef struct semaphore// semaphore {struct semaphore* semLink;// link to next semaphore char* name;// semaphore name (malloc) int state;// state (count) int type;// type (binary/counting) int taskNum;// tid of creator PQueue 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 - Tasking73 Project 2 Assignment

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 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 - Tasking74 Project 2 Assignment

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 - Tasking75 Project 2 Assignment

Step 4c: Verification BYU CS 345 Demo Project 2 - Tasking76 #Task NamePriorityTime sliceBlocking Semaphore 0CLI w/pseudo-input interrupts51 inBufferReady 1-9TenSeconds101 tics10sec 10sTask1201 sTask10 11sTask2201 sTask11 12ImAlive11None 13ImAlive11None Project 2 Assignment

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. Project 2 - Tasking77 createTask("myShell",// task name P1_shellTask,// task 5,// task priority argc,// task arg count argv// task argument pointers ); #include 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

BYU CS 345Project 2 - Tasking78

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 345Threads79

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 345Threads80

BYU CS 345Project 2 - Tasking81 Task Scheduling Ready Priority Queue Semaphore Priority Queue … SWAP SEM_SIGNALSEM_WAIT SEM_SIGNALSEM_WAIT SEM_SIGNALSEM_WAIT Executing Scheduler / Dispatcher Scheduling

BYU CS 345Threads82 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

BYU CS 345Project 2 - Tasking83 setjmp / longjmp #include 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

BYU CS 345Project 2 - Tasking84 Multi-threading in C setjmp/longjmp // new threads 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); } myThread(); } // schedule threads while (1) { tid = scheduler(); if (setjmp(k_context) == 0) { longjmp(tcb[tid].context, 3); } jmp_buf k_context; int tid; // my thread void myThread() { while (1) { if(!setjmp(tcb[tid].context)) longjmp(k_context,2); // execute function }

BYU CS 345Project 2 - Tasking85 Multi-tasking in C setjmp/longjmp

BYU CS 345Project 2 - Tasking86

BYU CS 345Project 2 - Tasking87 Multi-tasking in C setjmp/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 }

Step 1: Priority Queue Create a priority queue typedef int TID;// task ID typedef int Priority;// task priority typedef int* PQueue;// priority queue PQueue rq;// ready queue rq = (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>=0find and delete tid from q -1return highest priority tid inttid(if found and deleted from q) -1(if q empty or task not found) BYU CS 345Project 2 - Tasking88  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