fred: push #4 // Allocate j - it will be at [fp] ld [fp+12] -> %r0 // Load x into r0 st %r0 -> [fp] // And store it to j ld [fp+16] -> %r0 // Load y ld [fp] -> %r1 // And j; add %r0, %r1 -> %r0 // Add them st %r0 -> [fp+16] // Store the result into y ld [fp+16] -> %r0 // Return y in register r0 ret |
st %r2 -> [sp]-- |
push #4 st %g1 -> [fp] ld [fp] > %r0 ld [fp+12] -> %r1 add %r0, %r1 -> %r0 ld [fp+16] -> %r1 add %r0, %r1 -> %r0 st %r0 -> [sp]-- jsr e |
So, 9*4 = 36 = 0x24, and the answer is 0x4010+0x24 = 0x4034.
0xfff68 (adding): This is 4 bytes past the jsr instruction that called a.
1 0x8027a8: 0x28 or 40 2 0x8027a8: 0x8027d0 3 0x8027a8: 0x30 or 48 4 0x8027a8: 0x802750 5 0x8027a8: 0x18 or 24 6 0x8027a8: 0x802710 7 0x8027a8: 0x40 or 64 8 0x8027a8: 0x802768 9 0x8027a8: 0x18 or 24 10 0x8027a8: 0x802780 11 0x8027a8: 0x28 or 40 12 0x8027a8: 0x802800 13 0x8027a8: 0x20 14 0x8027a8: 0x802774 | 1 0x8075a8: 0x30 or 48 2 0x8075a8: 0x8075d8 3 0x8075a8: 0x28 or 40 4 0x8075a8: 0x807548 5 0x8075a8: 0x18 or 24 6 0x8075a8: 0x807530 7 0x8075a8: 0x18 or 24 8 0x8075a8: 0x807560 9 0x8075a8: 0x28 or 40 10 0x8075a8: 0x807588 11 0x8075a8: 0x20 or 32 12 0x8075a8: 0x807600 13 0x8075a8: 0x40 or 64 14 0x8075a8: 0x80756c | 1 0x87a1d0: 0x18 or 24 2 0x87a1d0: 0x87a1e8 3 0x87a1d0: 0x28 or 40 4 0x87a1d0: 0x87a160 5 0x87a1d0: 0x30 or 48 6 0x87a1d0: 0x87a120 7 0x87a1d0: 0x40 or 64 8 0x87a1d0: 0x87a190 9 0x87a1d0: 0x18 or 24 10 0x87a1d0: 0x87a1a8 11 0x87a1d0: 0x28 or 40 12 0x87a1d0: 0x87a110 13 0x87a1d0: 0x20 or 32 14 0x87a1d0: 0x87a19c |
Problem 1: You are holding the mutex while you perform the second fread(). Let's suppose that the client writes an integer and then waits 60 seconds before writing the second integer. Then the interact() thread will lock out all of the other threads for 60 seconds, potentially delaying all of the other clients.
Solution 1: Instead of reading twice to x, add a second variable, say y, and do the two fread() calls before you lock the mutex. Then, when you lock the mutex, you can update data with both integers. That way, you don't lock the mutex while waiting for the second integer.
Problem 2: You are holding the mutex while you do the fwrite() and fflush(). If the connection to the client is slow, then you are locking out the other threads during this slow operation.
Solution 2: While you're holding the mutex, make a copy of data. Then unlock the mutex and write the copy. That way, you don't lock the mutex while performing the potentially slow fwrite()/fflush().
void find_match(Person *me, char *keyword) { JRB tmp; Person *match; pthread_mutex_lock(lock); tmp = jrb_find_str(tree, keyword); /* Look up the keyword */ if (tmp == NULL) { /* If it's not there, put me into the tree and wait. */ jrb_insert_str(tree, keyword, new_jval_v((void *) me); pthread_cond_wait(me->cond, lock); /* When I unblock, my match has been set and I have been delete from the tree. */ } else { /* If the keyword is there, make the match, remove */ match = (Person *) tmp->val.v; /* the match from the tree, set the match fields, */ jrb_delete_node(tmp); /* and wake up the match. */ me->match = match; match->match = me; pthread_mutex_signal(match->cond); } pthread_mutex_unlock(lock); return; } |
Part B: This can happen with the following sequence:
#include <stdio.h> #include <stdlib.h> #include <unistd.h> #include "sockettome.h" #include <sys/wait.h> int main() { int sock, fd; int p[2]; int kim, khloe; int pid, status; int khloe_done; int ndone; sock = serve_socket(90210); fd = accept_connection(sock); pipe(p); kim = fork(); if (kim == 0) { /* Set up kim and let her execute */ dup2(fd, 0); /* Stdin comes from the socket. */ dup2(p[1], 1); /* Stdout goes to the pipe */ close(p[0]); close(p[1]); close(fd); execlp("kim", "kim", NULL); exit(1); /* Cardinal sin. */ } khloe = fork(); /* Set up khloe to read from kim and write to the socket. */ if (khloe == 0) { dup2(p[0], 0); dup2(fd, 1); close(p[0]); close(p[1]); close(fd); execlp("khloe", "khloe", NULL); exit(1); /* Cardinal sin. */ } khloe_done = 0; /* Wait for khloe to finish. You need to handle the case */ ndone = 0; /* where kim finishes before khloe, and count the number of */ /* children who have finished. */ while (!khloe_done) { pid = wait(&status); ndone++; if (pid == khloe) khloe_done = 1; } if (fork() == 0) { /* Now fork off kourtney and have her take over for khloe. */ dup2(p[0], 0); dup2(fd, 1); close(p[0]); close(p[1]); close(fd); execlp("kourtney", "kourtney", NULL); exit(1); /* Cardinal sin. */ } /* Close all extraneous file descriptors and wait for the rest of the children to exit. */ close(p[0]); close(p[1]); close(fd); while (ndone < 3) { pid = wait(&status); ndone++; } return 0; } |