140 likes | 161 Views
Another Look at Sem2. P1 and P2 runnable P1 runs, calls wait(), and continues Task switch to P2 P2 runs, waits and blocks P1 continues, signals and term. P2 continues, signals and term. signal. wait. OS/other. process 2. process 1. void os_signal(sem2 *s) {
E N D
Another Look at Sem2 P1 and P2 runnable P1 runs, calls wait(), and continues Task switch to P2 P2 runs, waits and blocks P1 continues, signals and term. P2 continues, signals and term. signal wait OS/other process 2 process 1 void os_signal(sem2 *s) { save_flags(); cli(); scount++; if (scount <= 0) { wake_up_interruptible(&Q); restore_flags(); } void os_wait(sem2 *s) { save_flags(); cli(); scount--; if (scount < 0) { interruptible_sleep_on(&Q); } restore_flags() } • cli() not strictly necessary but though some kernel functions can cause user space page fault, leading to unplanned context switch. • Alternative: wait_event_interruptible(&Q, scount < 0); CSE 466 – Fall 2000 - Introduction - 1
ISR TOP Kernel/driver OS/other process 2 process 1 Reentrant Sonar Driver (The Lab Requirements) INIT ECHO open read open Wake P1,P2 read P1, P2 get Same reading P2 could get a Newer reading if P1 or some other Process starts and Completes a new Measurement before P2 gets to run again. • No limit to number of processes that can open /dev/sonar at once • Read() always returns a fresh measurement – starts a new one or returns the one in progress. • All blocked processes return the current reading or later one. • write() unsupported, return –1; • Example Sequence of Events • Each process calls open() then read() • Process 1 call blocks in read() after initiating the Sonar measurement (sleeps on a wait queue) • Process 2 blocks in read() for results on current measurement • ISR wakes up all of the processes on the wait queue (top half?) • Process 1 resumes in the driver and returns the reading • Process 2 resumes in the driver and returns the reading CSE 466 – Fall 2000 - Introduction - 2
Linux Interrupt Structure (Sonar Example) • Linux Nomenclature for Interrupt handling • Top Half – the actual ISR. • Bottom Half – runs each time OS gets control if queued up by top half user space kernel space Top Half: Signal Driver (wake_up) ECHO task queue User Process High Level non-time Critical Processing s =open(“/dev/sonar”,..)read(s,distance,n); Not used in this case Watch for shared data betweenisr and device driver read() sonar_read() Compute distance, Copy to user space INIT CSE 466 – Fall 2000 - Introduction - 3
Problem Decomposition – A Case Study • Robot Collision Avoidance System • Sensors • Electronic Compass and Sonar Range Finder • Low Priority Processing • Knowing where it is and deciding how to get where its going • Time Critical Processing (device time scales) us - ms • Sonar Travel Time • Motor pulse train, and speed measurement • Time Critical on Human Time Scales ~100Hz • Collision avoidance, traction control, motor ramp • Partition into Linux user process, top half, bottom half, hardware User Process (Task switch) Mapping, Planning, Plan Execution (Control Algorithm) Bottom Half (OS tick) Collision Avoidance Motor Ramp Traction Assist Top Half (interrupt) Motor Pulse Train Motor Speed Measurement Sonar Time of Flight CSE 466 – Fall 2000 - Introduction - 4
Motor Interface • Open() • get exclusive control • Read() • return current actual speed • Write() • set desired speed (return error?) • Close() • stop motor and release • control • Device Driver • implement open,read,write,close • implement ramping, traction control continuously • Successful turns of the motor should generate interrupts so that the driver can know the speed • User Program and/or bottom half • determine desired speed • handle discrepancy between desired and actual speed CSE 466 – Fall 2000 - Introduction - 5
Schedule of task queues…bottom halves in Linux blah() blah() blah() other app Interrupt (motor turn) TOP HALF Increment turn count • Compute average speed since last execution of bottom half. Clear turn count. • Put speed and time into queue. Letqueue overwrite old data as necessary BOT. HALF blah() blah() blah() rti sys callor tick OS: Do Tick or System Call Device Driver arrows represent passage of control not data EXECUTE TASK QUEU myapp blah() read() blah() Block if queue is empty, return all speed measurements in the queue CSE 466 – Fall 2000 - Introduction - 6
As a Task Diagram unblocked motor_read done Task Switch BH run BH queued two measurments in the queue OS chance myapp blocked in driver ISR TOP ISR BOT BH run Motor driver OS/other myapp process 2 process 1 myapp done P2 read Blocks, Task Q runs Unblocks Tick Tick myapp: read() Bottom half queues: scheduler, timer, immediate CSE 466 – Fall 2000 - Introduction - 7
Linux Interprocess Communication Producer Consumer w/ Pipes and Fork() void main() { int pfds[2]; pipe(pfds); if (fork()) producer(); else consumer(); } void producer() { // serial? int q = pfds[0]; while (1) {generate_data(buf); write(q, buf, n);} } void consumer() { int q = pfds[1]; while (1) {read(q, buf, n); process_data(buf);} } • Single Reader, Single Writer • Kernel ensures mutual exclusion (Read/Write are system calls) CSE 466 – Fall 2000 - Introduction - 8
FIFO’s, which are named pipes • Process 1 void main() { mknod(“/tmp/myfifo”, S_IFIFO, ); // create a FIFO file node f = open(“/tmp/myfifo”, O_WRONLY); while (1) {generate_data(buf); write(q, buf, n);} } • Process 2 void main() { f = open(“/tmp/myfifo”, O_RDONLY); while (1) {read(q, buf, n); process_data(buf);} } • Works for “unrelated” processes • Multiple writers, Multiple readers • Kernel ensures mutual exclusion • Kernel does not control interleaving of writers, readers CSE 466 – Fall 2000 - Introduction - 9
Impement a FIFO w/ a Device Driver CSE 466 – Fall 2000 - Introduction - 10
Shared Memory • Can we do this with a device driver? • There are dedicated systems calls to support shared memory which are more efficient than device drivers CSE 466 – Fall 2000 - Introduction - 11
Message Queues • Like FIFO’s but for data structures rather than bytes (Structured I/O) System calls • Create a message queue • Put messages on the message queue(q, message_pointer, message_type) • Get messages from the queue(q, message_pointer, message_type); • It’s a really ugly in C • The data structure is serialized, but you can’t tell what the type is. • Sender and Receiver have to agree on integer designations for data types) • Java (and maybe C++) is sooo much better at this kind of thing CSE 466 – Fall 2000 - Introduction - 12
Implement w/ Shared Memory • FIFO • Shared Memory CSE 466 – Fall 2000 - Introduction - 13
Sockets -- Networking • s = socket(int domain, int type, int protocol) -- protocol is usually associated with domain but not always • domain: internet, UNIX, apple-talk…etc. How to interpret that address • bind(int s, sockaddr *addr, n) • s is the socket identifier • sockaddr is the address (june.cs.washington.edu) • n is the length of the address • Now it is like a pipe, you can do read/write, send/recv, listen/accept. • Several types • stream • datagram • sequential • raw • The protocol stack • mapping from application level abstractions (open, read, socket) to HW and back CSE 466 – Fall 2000 - Introduction - 14