From: Ramakrishnan Muthukrishnan Date: Fri, 1 Jul 2011 17:05:51 +0000 (+0530) Subject: Ok, we are not yet in ch 4. Renaming a bunch of files. X-Git-Url: https://git.rkrishnan.org/pf/content/en/seg?a=commitdiff_plain;h=6dbee26f2d8117532bb7932066dbda4608c7aaea;p=sicp.git Ok, we are not yet in ch 4. Renaming a bunch of files. --- diff --git a/src/sicp/ex3_46.rkt b/src/sicp/ex3_46.rkt new file mode 100644 index 0000000..2092575 --- /dev/null +++ b/src/sicp/ex3_46.rkt @@ -0,0 +1,30 @@ +#lang racket + +(define (test-and-set! cell) + (if (car cell) + true + (begin (set-car! cell true) + false))) +#| + +If there are two concurrent processes doing the above test-and-set! function, +there could be many things that can happen. + +Assume that the cell is having a #f value initially. Process 1 tests the +value and finds that it is false. At the same instant, Process 2 also tests +the cell and finds that it is false and both of them set the cell to true at +the same instant. Both the processes get a false value from test-and-set! +and think that they are holding the mutex. + +Another scenario is when the Process 1 does the test and then finds that the +cell is false. Next Process 2's test is executed and it also finds that the +cell is false. Now, both of them proceed to do a set and so both gets the +mutex. + +In reality, only one of the processes should hold a mutex (Mutual exclusion). +So, that assumption is violated in this case. As footnote 47 indicate, if the +instruction that atomically implement test-and-set! is executed at the same +cycle by two separate concurrent processes, a hardware arbiter resolves who +gets the chance to execute it. + +|# diff --git a/src/sicp/ex3_47.rkt b/src/sicp/ex3_47.rkt new file mode 100644 index 0000000..edd9d09 --- /dev/null +++ b/src/sicp/ex3_47.rkt @@ -0,0 +1,64 @@ +#lang racket + +;; semaphore implementation using mutex +(define (make-mutex) + (let ([cell (mcons #f '())]) + (define (the-mutex m) + (cond [(eq? m 'acquire) + (when (test-and-set! cell) + (the-mutex 'acquire))] ;; loop till we acquire the mutex + [(eq? m 'release) (clear! cell)])) + the-mutex)) + +(define (clear! cell) + (set-mcar! cell #f)) + +(define (test-and-set! cell) + (if (mcar cell) + #t + (begin (set-mcar! cell #t) + #f))) + +;; semaphore implementation +(define (make-semaphore n) + (let ([cell 0] + [mutex (make-mutex)]) + (define (the-semaphore s) + (cond [(eq? s 'acquire) + (mutex 'acquire) + (if (>= (+ cell 1) n) + (begin + (mutex 'release) + (the-semaphore 'acquire)) + (begin + (set! cell (+ cell 1)) + (mutex 'release)))] + [(eq? s 'release) + (mutex 'acquire) + (when (> cell 0) + (set! cell (- cell 1))) + (mutex 'release)])) + the-semaphore)) + +;; using test-and-set! +(define (make-semaphore n) + (let ([cell 0] + [flag #f]) + (define (the-semaphore s) + (cond [(eq? s 'acquire) + (if (test-and-set! flag) + (the-semaphore 'acquire)) + (if (>= (+ cell 1) n) + (begin + (clear! flag) + (the-semaphore 'acquire)) + (begin + (set! cell (+ cell 1)) + (clear flag)))] + [(eq? s 'release) + (if (test-and-set! flag) + (the-semaphore 'acquire)) + (when (> cell 0) + (set! cell (- cell 1))) + (clear! flag)])) + the-semaphore)) diff --git a/src/sicp/ex3_48.rkt b/src/sicp/ex3_48.rkt new file mode 100644 index 0000000..2163808 --- /dev/null +++ b/src/sicp/ex3_48.rkt @@ -0,0 +1,46 @@ +#lang racket + +#| + +by giving a unique number to each account, we are ordering the access to the account +in a specific manner (say in the ascending order of the number). The reason why deadlock +occurs is be cause of the concurrent access to the accounts in a specific order (Paul +attempts to transfer a1 and a2 while Peter attempts to transfer a2 and a1. With the +suggested change, both will concurrently try to access a1 first but only one of them +will get access while the other will wait until the serializer for a1 is released. + +|# + +(define (make-account-and-serializer account-number balance) + (define (withdraw amount) + (if (>= balance amount) + (begin (set! balance (- balance amount)) + balance) + "Insufficient funds")) + (define (deposit amount) + (set! balance (+ balance amount)) + balance) + (let ((balance-serializer (make-serializer))) + (define (dispatch m) + (cond ((eq? m 'withdraw) withdraw) + ((eq? m 'deposit) deposit) + ((eq? m 'balance) balance) + ((eq? m 'account-number) account-number) + ((eq? m 'serializer) balance-serializer) + (else (error "Unknown request -- MAKE-ACCOUNT" + m)))) + dispatch)) + +(define (serialized-exchange account1 account2) + (let ((serializer1 (account1 'serializer)) + (serializer2 (account2 'serializer)) + (number1 (account1 'account-number)) + (number2 (account2 'account-number))) + (if (< number1 number2) + ((serializer2 (serializer1 exchange)) + account1 + account2) + ((serializer1 (serializer2 exchange)) + account1 + account2) +)) \ No newline at end of file diff --git a/src/sicp/ex3_49.rkt b/src/sicp/ex3_49.rkt new file mode 100644 index 0000000..b326820 --- /dev/null +++ b/src/sicp/ex3_49.rkt @@ -0,0 +1,11 @@ +#lang racket + +#| + +Process 1 needs access to a shared resource depending on some runtime condition and needs +another resource depending on another condition. + +Consider another similar process being executed concurrently. We cannot determine +the order of the resource acquisition apriori in this case. + +|# \ No newline at end of file diff --git a/src/sicp/ex4_46.rkt b/src/sicp/ex4_46.rkt deleted file mode 100644 index 2092575..0000000 --- a/src/sicp/ex4_46.rkt +++ /dev/null @@ -1,30 +0,0 @@ -#lang racket - -(define (test-and-set! cell) - (if (car cell) - true - (begin (set-car! cell true) - false))) -#| - -If there are two concurrent processes doing the above test-and-set! function, -there could be many things that can happen. - -Assume that the cell is having a #f value initially. Process 1 tests the -value and finds that it is false. At the same instant, Process 2 also tests -the cell and finds that it is false and both of them set the cell to true at -the same instant. Both the processes get a false value from test-and-set! -and think that they are holding the mutex. - -Another scenario is when the Process 1 does the test and then finds that the -cell is false. Next Process 2's test is executed and it also finds that the -cell is false. Now, both of them proceed to do a set and so both gets the -mutex. - -In reality, only one of the processes should hold a mutex (Mutual exclusion). -So, that assumption is violated in this case. As footnote 47 indicate, if the -instruction that atomically implement test-and-set! is executed at the same -cycle by two separate concurrent processes, a hardware arbiter resolves who -gets the chance to execute it. - -|# diff --git a/src/sicp/ex4_47.rkt b/src/sicp/ex4_47.rkt deleted file mode 100644 index edd9d09..0000000 --- a/src/sicp/ex4_47.rkt +++ /dev/null @@ -1,64 +0,0 @@ -#lang racket - -;; semaphore implementation using mutex -(define (make-mutex) - (let ([cell (mcons #f '())]) - (define (the-mutex m) - (cond [(eq? m 'acquire) - (when (test-and-set! cell) - (the-mutex 'acquire))] ;; loop till we acquire the mutex - [(eq? m 'release) (clear! cell)])) - the-mutex)) - -(define (clear! cell) - (set-mcar! cell #f)) - -(define (test-and-set! cell) - (if (mcar cell) - #t - (begin (set-mcar! cell #t) - #f))) - -;; semaphore implementation -(define (make-semaphore n) - (let ([cell 0] - [mutex (make-mutex)]) - (define (the-semaphore s) - (cond [(eq? s 'acquire) - (mutex 'acquire) - (if (>= (+ cell 1) n) - (begin - (mutex 'release) - (the-semaphore 'acquire)) - (begin - (set! cell (+ cell 1)) - (mutex 'release)))] - [(eq? s 'release) - (mutex 'acquire) - (when (> cell 0) - (set! cell (- cell 1))) - (mutex 'release)])) - the-semaphore)) - -;; using test-and-set! -(define (make-semaphore n) - (let ([cell 0] - [flag #f]) - (define (the-semaphore s) - (cond [(eq? s 'acquire) - (if (test-and-set! flag) - (the-semaphore 'acquire)) - (if (>= (+ cell 1) n) - (begin - (clear! flag) - (the-semaphore 'acquire)) - (begin - (set! cell (+ cell 1)) - (clear flag)))] - [(eq? s 'release) - (if (test-and-set! flag) - (the-semaphore 'acquire)) - (when (> cell 0) - (set! cell (- cell 1))) - (clear! flag)])) - the-semaphore)) diff --git a/src/sicp/ex4_48.rkt b/src/sicp/ex4_48.rkt deleted file mode 100644 index 2163808..0000000 --- a/src/sicp/ex4_48.rkt +++ /dev/null @@ -1,46 +0,0 @@ -#lang racket - -#| - -by giving a unique number to each account, we are ordering the access to the account -in a specific manner (say in the ascending order of the number). The reason why deadlock -occurs is be cause of the concurrent access to the accounts in a specific order (Paul -attempts to transfer a1 and a2 while Peter attempts to transfer a2 and a1. With the -suggested change, both will concurrently try to access a1 first but only one of them -will get access while the other will wait until the serializer for a1 is released. - -|# - -(define (make-account-and-serializer account-number balance) - (define (withdraw amount) - (if (>= balance amount) - (begin (set! balance (- balance amount)) - balance) - "Insufficient funds")) - (define (deposit amount) - (set! balance (+ balance amount)) - balance) - (let ((balance-serializer (make-serializer))) - (define (dispatch m) - (cond ((eq? m 'withdraw) withdraw) - ((eq? m 'deposit) deposit) - ((eq? m 'balance) balance) - ((eq? m 'account-number) account-number) - ((eq? m 'serializer) balance-serializer) - (else (error "Unknown request -- MAKE-ACCOUNT" - m)))) - dispatch)) - -(define (serialized-exchange account1 account2) - (let ((serializer1 (account1 'serializer)) - (serializer2 (account2 'serializer)) - (number1 (account1 'account-number)) - (number2 (account2 'account-number))) - (if (< number1 number2) - ((serializer2 (serializer1 exchange)) - account1 - account2) - ((serializer1 (serializer2 exchange)) - account1 - account2) -)) \ No newline at end of file diff --git a/src/sicp/ex4_49.rkt b/src/sicp/ex4_49.rkt deleted file mode 100644 index b326820..0000000 --- a/src/sicp/ex4_49.rkt +++ /dev/null @@ -1,11 +0,0 @@ -#lang racket - -#| - -Process 1 needs access to a shared resource depending on some runtime condition and needs -another resource depending on another condition. - -Consider another similar process being executed concurrently. We cannot determine -the order of the resource acquisition apriori in this case. - -|# \ No newline at end of file