1 / 31

Deadlock

Deadlock. What is deadlock? A group of processes permanently stuck waiting for each other Deadlock Example Process P Process Q (1) Get A (5) Get B (2) Get B (6) Get A (3) Release B (7) Release A (4) Release A (8) Release B Possible execution paths 5, 6, 7, 8, … – No problem

tyme
Download Presentation

Deadlock

An Image/Link below is provided (as is) to download presentation Download Policy: Content on the Website is provided to you AS IS for your information and personal use and may not be sold / licensed / shared on other websites without getting consent from its author. Content is provided to you AS IS for your information and personal use only. Download presentation by click this link. While downloading, if for some reason you are not able to download a presentation, the publisher may have deleted the file from their server. During download, if you can't get a presentation, the file might be deleted by the publisher.

E N D

Presentation Transcript


  1. Deadlock • What is deadlock? • A group of processes permanently stuck waiting for each other • Deadlock Example Process P Process Q (1) Get A (5) Get B (2) Get B (6) Get A (3) Release B (7) Release A (4) Release A (8) Release B • Possible execution paths • 5, 6, 7, 8, … – No problem • 5, 6, 1, … – P blocks, but will finish • 5, 1, … – Deadlock inevitable • 1, 5, … – Deadlock inevitable • 1, 2, 5, … – Q blocks, but will finish • 1, 2, 3, 4, … – No problem

  2. Deadlock • Reusable Resources • Can only be used by one process at a time. After use, can be reassigned to another process (printer, memory, files, etc.) • In previous example, if “A” = file, and “B” = tape drive, deadlock can occur • Can occur with memory allocation if we don’t do swapping • 200K available, both processes want 80K, then make second request for 70K • Consumable Resources • Can be created or destroyed (signals, messages) • No fixed limit on # of resources • Can deadlock if both waiting for a message from the other

  3. Conditions for Deadlock • All must hold for deadlock to occur • Mutual Exclusion • Only one process can hold the resource at any given time • Hold and Wait • A process may hold resources while requesting others • No Preemption • No resource may be forcibly removed from a process • Circular Wait (event) • A closed chain of process exists, each waiting for a resource held by the next process in the chain • Figure 6.5, page 273:

  4. Deadlock Prevention • Can prevent deadlock by forbidding one of the conditions • Forbid Mutual Exclusion • Generally not reasonable • Multiple read-only access often ok • Forbid Hold and Wait • Ask for all resources at one time • May block a process for a long time when it can be making progress • Wait for resources it doesn’t yet need • May tie up unneeded resources • May hold resources that are not needed immediately • May not know what to request • Especially true for interactive processes • May request resources because they are needed in some instances, but not always

  5. Deadlock Prevention • Forbid No Preemption • Take resources away from waiting processes • Only feasible if state can be saved • Examples: CPU, Memory • Not usable for Files, Printer, etc. • Forbid Circular Wait • Define a linear order on items • If it needs resources 3, 15, 6, 9, and 4 then must request in the order 3, 4, 6, 9, 15 • Cannot have circular wait because a process cannot have 9 and request 5 • May not be easy to define the order (files) • May force an awkward order of requesting resources • May have to request resource 3 in order to request 4, even when 4 is needed now but 3 is not needed until much later

  6. Deadlock Avoidance • Allow general requests, but make choices to avoid deadlock • Assume we know the maximum requests (claims) for each process • Process must state it needs a max of 5 A objects, 3 B objects, 2 C objects. • Do not need to use its max claims • Ok to set max=5 and only use 3 • Can make requests at any time and in any order • Process Initiation Denial • Track current allocations • Assume all processes may make maximum requests at the same time • Only start process if it can’t result in deadlock regardless of allocations

  7. Resource Allocation Denial • Also called banker’s algorithm • safe state – We can finish all processes by some scheduling sequence • Example: Finish P1, P4, P2, P5, P3 • Reject a request if it exceeds the processes’ declared maximum claims • Grant a request if the new state would be safe • Determining if a state is safe • Find any process Pi for which we can meet it’s maximum requests • Don't forget already allocated resources • Mark Pi as “done”, add its resources to available resource pool • State is safe if we can mark all processes as “done” • Block a process if the resources are not currently available or the new state is not safe

  8. Avoidance Example • Figure 6.6, page 277 • Claim Matrix: A B C P1 3 2 2 P2 6 1 3 P3 3 1 4 P4 4 2 2 • Allocation Matrix: A B C P1 1 0 0 P2 5 1 1 P3 2 1 1 P4 0 0 2 • Total Resources: 9 3 6 • Available: 1 1 2 • P1 wants 1 A and 1 C, is it ok? • P4 wants 1 B, is it ok? • Still requires the process to declare its max request at start

  9. Deadlock Detection • Avoidance methods tend to limit access to resources • Instead, grant arbitrary requests and note when deadlock happens • Can vary how often we check • Early detection vs. overhead of checks • Algorithm (Page 280) • Preparation: • Create table of process requests, current allocations • Note available resources • Mark processes with no resources • Mark any process whose requests can be met (requests £ available resources) • Include resources from that process as ‘available’ (this process can finish) • If multiple processes available, pick any • If any processes cannot be marked, they are part of a deadlock

  10. Detection Example • Figure 6.9, page 281 • Requests: A B C D E P1 0 1 0 0 1 P2 0 0 1 0 1 P3 0 0 0 0 1 P4 1 0 1 0 1 • Allocation: A B C D E P1 1 0 1 1 0 P2 1 1 0 0 0 P3 0 0 0 1 0 P4 0 0 0 0 0 • Available 0 0 0 0 1 • Mark P4 (nothing allocated) • Mark P3, new available: 0 0 0 1 1 • Cannot mark P1 or P2, so we are deadlocked

  11. Detection Example 2 • Requests: A B C P1 0 0 0 P2 2 0 2 P3 0 0 0 P4 1 0 0 P5 0 0 2 • Allocation: A B C P1 0 1 0 P2 2 0 0 P3 3 0 3 P4 2 1 1 P5 0 0 2 • Available 0 0 0 • Is this system deadlocked?

  12. Deadlock Recovery • Several possible approaches • Abort all deadlocked processes • Simple but common • Back up processes to a previously saved checkpoint, then restart • Assumes we have checkpoints and a rollback mechanism • Runs risk of repeating deadlock • Assumes that the deadlock has enough timing dependencies it won’t happen • Selectively abort processes until deadlock broken • Preempt resources until deadlock broken • Must roll back process to checkpoint prior to acquiring key resource

  13. Mixed Strategy • May group resources into classes, have a different deadlock strategy for each class • Swap Space • Prevent Deadlocks by requiring all space to be allocated at once • Avoidance also possible • Tapes/Files • Avoidance can be effective here • Prevention by ordering resources also possible • Main Memory • Preemption a good approach • Internal Resources (channels, etc.) • Prevention by ordering resources • Can use linear ordering between classes

  14. Dining Philosophers • Five philosophers who alternately think and eat • Shares a fork with each neighbor • Assume each philosopher picks up left fork, then right fork, then eats • Deadlock if all enter at once • Figure 6.10, page 283

  15. Solving Dining Phil. • Buy more Forks • Equivalent to increasing resources • Put fork down if 2nd fork busy • Can produce “livelock” if philosophers stay synchronized • Room Attendant • Only let 4 of the philosophers into the room at once • May have 4 philosophers in room, but only 1 can eat • Left-Handed Philosophers • Grab forks in the other order (right fork, then left fork) • Any mix will avoid deadlock (effective linear ordering on forks)

  16. Linux Fork() • fork() • returns 0 to child • return child_pid to parent • Parent is responsible to look after children • Failure to do so can create zombies • pid = wait( &status ) to explicitly wait for the child to terminate • signal(SIGCHLD, SIG_IGN) to ignore child-termination signals • May also set SIGCHLD to call a specified subroutine when a child dies

  17. #include <stdio.h> #include <signal.h> void main() { int cnt = 15; int pid; char buff[100]; /* create a new process */ if ((pid = fork()) == -1) { perror("Fork failed, call system manager!"); exit(1); } if (pid) { /* we are the parent, tell system to ignore child termination messages */ signal(SIGCHLD, SIG_IGN); while (cnt--) { /* lets look for the child */ printf("The child has a pid of %d, my pid is %d\n", pid, getpid()); printf("----------------------\n"); sprintf(buff, "%s %d", "ps -aux | grep ", pid); system(buff); /* execute the command */ printf("----------------------\n"); sleep(1); /* let some time pass… */ } exit(0); } else { /* here is the child code */ int cnt = 8; while (cnt) { printf("[child] I'm alive...cnt = %d\n", cnt--); sleep(1); } printf("[child] Preparing to exit with status 7\n"); exit(7); /* quit */ } } /* end of program */ Fork() Example

  18. Linux Semaphores • Key - 4 byte value for the “name” • Create/access semaphores • id = semget( KEY, Count, IPC_CREAT | PERM ) • id = semget( KEY, 0, 0 ) • Perm = file permission bits (0666) • to create only (fails if exists) use IPC_CREAT|IPC_EXCL|PERM • Count = # of semaphores to create • Working with semaphore value • i = semctl( id, num, SETVAL, v ) • val= semctl( id, num, GETVAL, 0 ) • Deleting semaphores • i = semctl( id, 0, IPC_RMID, 0 ) • ipcs – Program to list semaphores/etc. • ipcrm sem id – Program to delete a semaphore

  19. Semaphore Operations • Semaphore Structure struct sembuf { short sem_num; (semaphore ID) short sem_op; (change amount) short sem_flg; (wait/don’t wait) } op; • sem_flg can be 0 or IPC_NOWAIT • Wait(): • op.sem_op = -1 (decrement) • res = semop( id, &op, 1 ) • Signal(): • op.sem_op = 1 (increment) • res = semop( id, &op, 1 ) • Can do multiple signal/wait ops • res = semop( id, oparray, opcount )

  20. #include <sys/types.h> #include <sys/ipc.h> #include <sys/sem.h> #include <errno.h> #define PERM 0666 #define KEY 0x12348765 main() {int id, result; id = semget(KEY,1, IPC_CREAT|IPC_EXCL|PERM); printf("status of create = %d\n", id); if(id == -1){perror("Bad Semaphore Create"); exit(0);} /* set the value to one */ result = semctl(id,0,SETVAL,1); if(result == -1){ perror("Bad SetVal call");exit(0);} printf("Semaphore created with an id of %d\n",id); } Create Example

  21. Wait Example #include <sys/types.h> #include <sys/ipc.h> #include <sys/sem.h> #include <errno.h> #define KEY 0x12348765 main() {int id, result; struct sembuf op[1]; id = semget(KEY,0,0); printf("status of get key = %d\n",id); if(id == -1) {perror("Bad Semaphore ID fetch"); exit();} /* initialize the op data structure */ op[0].sem_num = 0; /* the first one */ op[0].sem_op = -1; /* wait until we can add 1 */ op[0].sem_flg = 0; /* no options */ /* now try to get past the semaphore */ printf("Ready to test semaphore\n"); result = semop(id,op,1); if(result == -1){ perror("Bad Wait"); exit();} printf("Got past semaphore\n"); }

  22. Shared Memory • Create/Access Shared Memory • id = shmget( KEY, Size, IPC_CREAT | PERM ) • id = shmget( KEY, 0, 0 ) • Deleting Shared Memory • i = shmctl( id, IPC_RMID, 0 ) • Or use ipcrm • Accessing Shared Memory • memaddr = shmat( id, 0, 0 ) • memaddr = shmat( id, addr, 0 ) • Addr should be multiple of SHMLBA • memaddr = shmat( id, 0, SHM_READONLY ) • System will decide address to place the memory at • shmdt( memaddr ) • Detach from shared memory

  23. Creating Shared Memory #include <sys/types.h> #include <sys/ipc.h> #include <sys/shm.h> #include <errno.h> #define SIZE 512 /* shared mem buffer size */ #define PERM 0666 /* all can read write */ #define KEY 'JHL ' /* our key */ main() { int id; id = shmget(KEY,SIZE, IPC_CREAT|IPC_EXCL|PERM ); printf("status of create = %d\n",id); if(id == -1) perror("Bad Create"); }

  24. Writing Shared Memory #include <sys/types.h> #include <sys/ipc.h> #include <sys/shm.h> #include <string.h> #include <errno.h> #include <stdio.h> #define SIZE 512 /* shared memory buffer size */ #define KEY 'JHL ' /* our key */ main() { key_t key; int memoryid; char * location; /* the shmget will fail if the segment has not been created */ memoryid = shmget(KEY,SIZE,0); printf("status of key retrieval = %d\n",memoryid); if(memoryid == -1) {perror("Bad Key");exit();} /* we got the key now attach to the segment we will allow the system to chose the location (second parm) and we will want read/write access (third parm) */ location = (char *)shmat(memoryid,0,0); /* we want read write access */ printf("status of attach = %d\n",location); if (location == (char*)-1) {perror("Bad Attach");exit();} /* memory has been attached to,now copy string into the location */ printf("Enter string -> "); gets(location); printf("location contains: %s\n",location); }

  25. Unix Pipes • Creates a one-way connection between processes • Created using pipe() call • Returns a pair of file descriptors • pend[0] = read end • pend[1] = write end • Use dup() call to convert to stdin/stdout • Example: int pend[2] pipe( pend ) fork() parentchild close(pend[1]) close(pend[0]) write(pend[1],…) read(pend[0],…) close(pend[0]) close(pend[1])

  26. Unix Pipe Example /* A simple "pipe" demo --- Author: Jerry LeVan */ #include <stdio.h> #define DATA "Sample Data Sent Through A Pipe" main() { int sockets[2], child; /* create a pipe; doing it here assures that it will be open in the child */ if(pipe(sockets) <0){ perror("opening stream socket pair"); exit(10); } if((child = fork()) == -1) /* fork the child */ perror("fork"); else if (child) { char buf[1024]; /* this is the parent */ sleep(4); /* let the child do its stuff */ close(sockets[1]); /* close "write" side */ if ( read(sockets[0],buf,1024) < 0) perror("reading message"); printf("-->%s\n",buf); /* Do you know why this works? */ close(sockets[0]); /* shut "read" side */ }else { /* this is the child. It writes to the parent */ close(sockets[0]); /* close "read" side */ if ( write(sockets[1],DATA,sizeof(DATA)) < 0) perror("writing message"); close(sockets[1]); /* close "write" side */ printf("[child] I am outa here...\n"); exit(0); } }

  27. Unix Messages • Send information (type + data) between processes • Message Structure • long type • char text[] • Functions: • id = msgget( KEY, IPC_CREAT|…) • id = msgget( KEY, 0 ) • msgctl( id, IPC_RMID ) • msgsnd( id, buf, text_size, flags ) • msgrcv( id, buf, max_size, flags ) • Useful Flags • IPC_NOWAIT • MSG_NOERROR (truncate long messages to max_size)

  28. Other Unix Synchronization • Semaphores (discussed earlier) • Shared Memory (discussed earlier) • Signals • Used to inform processes of asynchronous events • Set up handler using • void handler( int sig_num ) { … } • sig_num is signal number so one handler can respond to several signals • signal( SIGxxx, handler) • One-time event – Must reset within handler if you want to keep handling this signal (Linux) • special value for handler • SIG_IGN – Ignore signal • SIG_DFL – Default action • Partial list (Table 6.2, page 288) • SIGHUP, SIGQUIT, SIGKILL, SIGALARM, SIGUSR1, SIGCLD • Send signal using kill command/call

  29. Solaris • Both Kernel and User-level calls • Mutual Exclusion Lock • mutex_enter() – Waiting processes can busy-wait or be suspended • mutex_exit() – Release lock • mutex_tryenter() – Get lock if not held • Condition Variables • Used in conjunction with a mutex lock • cv_wait() –The process will release the associated mutex before waiting, reacquire it before continuing • cv_signal() – Wake up one thread waiting on a given condition • cv_broadcast() – Wake up all threads • Mutex + Condition Variables can be used to implement monitors

  30. Solaris • Semaphores • sema_p() – Traditional Wait() • sema_v() – Traditional Signal() • sema_tryp() • Reader/Writer Lock • rw_enter() – Get lock as a reader or writer • rw_exit() – Release a lock • rw_tryenter() – Try to get a lock, but don’t wait if it isn’t available • rw_downgrade() – Convert a write lock to a read lock • rw_tryupgrade() – Try to convert a read lock into a write lock

  31. Windows 2000 • Synchronization Objects (table 6.3, page 292) • Process – Signals on termination • Thread – Signals on termination • File – Signal on I/O operation complete • Console Input – Signal on data ready • File Change Notification – Signal when a file system change matching a filter happens • Mutex – Provides mutual exclusion • Semaphore – Counting semaphore • Event – Announcement a system event has happened • Waitable Timer – Counter that records the passage of time

More Related