CSCI1600: Embedded and Real Time Software Lecture 25: Real Time Scheduling III Steven Reiss, Fall 2015
Total Bandwidth Server Initially e s = 0 and d = 0 When a new job with execution time e comes into an empty queue Set d = max(d,t) + e/u s Set e s = e When the server completes the current job, remove the job from the queue If there are more jobs, Set the server deadline to d+e q /u s and e s = e q
Example Periodic: P1(4,1), P2(6,3) Aperiodic: A3: e=2 at time 1, A4: e= 1 at time 2 First determine U s U p = ¼ + 3/6 = 0.75 U s = 0.25 (could be less)
Example At Start P1(4,1), P2(6,3), e s = 0, d = 0 A3: e=2 at time 1 At time 1: d = max(0,1) + 2 / 0.25 = 9, e s = 2 P1 P2 P3
Example P1(4,1), P2(6,3), P s (9,2) At time 3: new aperiodic job P t ( A4: e= 1 at time 2), but P s not done At time 7: P s finishes, P2 has deadline 12 P1 P2 P3
Example At time 7: d = d + e q /U s = 9 + 1/0.25 = 13, e s = 1 P s (13,1) P1 P2 P3
Example At time 7: d = d + e q /U s = 9 + 1/0.25 = 13, e s = 1 P s (13,1) P1 and P2 have deadlines of 12 P1 P2 P3
Handling Task Dependencies Suppose tasks depend on one another Represent this as a precedence relation T i -> T j if T i must precede T j Why would this arise? How can we schedule the result EDF doesn’t work directly
EDF* Scheduling Let D i be the deadline for task i Let e i be the execution time for task i Define D’ i as the modified deadline for task i D’ i = min(D i,MIN(T j dependent on T i )[D’ j – e j ] Then use EDF on the modified deadlines
Thread Scheduling All our schedules assume single core, single thread This might not be realistic today Can we just use these techniques for multithreaded scheduling? Using any available processor What can go wrong?
Thread Scheduling Assume m processors, m+1 tasks Tasks 1..m are (1,2e) for small e (2me < 1) Task m+1 is (1+e,1) What happens? Using EDF/RM/DM Tasks 1..m are all scheduled But then m+1 can’t run Even though there is lots of idle time Other anomalies are possible (esp. w/ synchronization)
Thread Scheduling Can still use the basic algorithms Assign each task to a particular thread Ensure the utilization of that thread is <= 1 (k) Then you can use EDF (RM/DM) to schedule the thread Optimal assignment is NP-hard But approximations are pretty good
Interprocess Communication Multiple tasks need to communicate We’ve covered shared memory Using synchronization where necessary When is synchronization necessary? What other means are there?
Mailboxes What it is A synchronized holder for a single message Operations create – initialize a mailbox structure accept – takes in a message pend – waits for a message post – sends a message Messages void * (arbitrary pointer)
Mailbox Implementation Mutex for operations Create: set up everything, empty mailbox Accept: check if mailbox is empty, if not, emtpy it Pend: Wait until the mailbox is non-empty Put task on wait queue for mailbox Then get message and return it Conflicts can be FIFO, priority-based, random
Mailbox Implementation Post: If queued tasks, find proper waiter and remove from queue Insert message into mailbox Let that task continue Else if there already is a message, return error Else save message and return Note that all operations are synchronized appropriately What mailboxes can’t do Multiple messages (but can prioritize) Blocking on post
Message Queues Similar to mailboxes Differences More than one message at a time Can be dynamic or fixed maximum sized Block on send At least optionally
Message Queue Implementation What does this look like Synchronized producer consumer queue Handling multiple readers and writers What this doesn’t handle Variable sized messages Communication without shared memory
Pipes Similar to message queues except Handle varying sized messages May be entirely byte oriented May take for messages Can work across processes if messages lack pointers Can work across machines But have to be wary of endian problems
Wider Scale Communications Might want to do more Communicate between processes Communicate between devices (e.g. in a car) Means for doing so Attached devices: point-to-point communication Busses Ethernet: MAC (Media Access Control), UDP Ethernet: TCP, IP
Internetworking UDP (covered in CSCI1680) Not very different from interacting with a bus Best effort delivery (no reliability guarantees, acks) You manage retries, assembly/dissembly, congestion Good for sensor updates, etc. TCP/IP Similar to a IPC pipe Adds reliability, byte stream interface Internally manages retries, ordering, etc. Web services, simple APIs
TCP/IP Sockets are like 2-way pipes Both sides can read/write independently Sockets are address by host-port Connection to a socket Create socket on the server Bind it to a known port (on the known host) Do an accept on the socket Create a socket on the client Connect to know server socket (connect) operation Server does accept on its socket This yields a new socket bound to that client
TCP/IP Lightweight implementation exist (even for Arduino) Library interface for lwIP (Light Weight IP) ip_input(pbuf,netif) Takes an IP package and the network interface as args Does TCP/IP processing for the packet tcp_tmr() Should be called every 250ms Does all TCP timer-base processing such as retransmission Event-based callbacks This is not sockets, but it is TCP/IP
lwIP Basics Initialization: tcp_init Manage all TCP connections tcp_tmr() Must be called every milliseconds sys_check_timeout() Calls tcp_tmr and other network related timers
lwIP Server Connection tcp_new : create a PCB for a new socket tcp_bind : bind that socket to a port on this host tcp_listen : listen for connections tcp_accept : specify a callback to call Passed routine called when someone tries to connect tcp_accepted : called from the routine to accept the connection
lwIP Client Connection tcp_new : create new PCB (socket) tcp_bind : bind the socket to target host/port tcp_connect : establish the connection Provides callback function Called when connected Or if there is an error in the connection
lwIP Sending Data tcp_sent : specify callback function Called when data acknowledged by remote host tcp_sndbuf : get maximum data that can be sent tcp_write : enqueues the data for write Can be via copy or in-place tcp_output : forces data to be sent
lwIP Receiving Data tcp_recv : specifies a callback function Function called when data is received Or when there is an error (connection closed) Calls tcp_recved to acknowledge the data
lwIP Other Functions tcp_poll : handle idle connections tcp_close : close a connnection tcp_abort : forcibly close a connection tcp_err : register an error handling callback
Simple Web Server Assuming the host IP is known Create a server socket on port 80 Listen for connections Read message from connection Should be header + body Simple message = header only Decode header, branch on URL Compute output page Send reply on the connection HTTP header + HTML body
Simple Web Communicator To send periodic updates Put together a message Simple HTTP header URL using ?x=v1&y=v2 to encode data Connect to Send the message Close connection
Simple Server Communicator Use arbitrary message format Use arbitrary host/port for the server Send and receive messages in that format
Sample Code: Minimal Server main() { struct tcp_pcb * pcb tcp_tcb_new(); tcp_bind(pcb,NULL,80); tcp_listen(pcb); tcp_accept(pcb,http_accept,NULL); /* main loop */ } http_accept(void * arg,struct tcp_pcb * pcb) { tcp_recv(pcb,http_recv,NULL); } http_recv(void * arg, struct tcp_pcb *pcb,struct pbuf * p) { // do something with packet p }
Next Time Real Time Operating Systems