Fixed cwd: Removed dynamic-wind and seperated things.

This commit is contained in:
marting 2000-06-20 08:44:01 +00:00
parent 6855de9ec8
commit 2c5a392584
1 changed files with 83 additions and 28 deletions

View File

@ -118,8 +118,16 @@
(define-record env (define-record env
c-struct ; An alien -- pointer to an envvec struct c-struct ; An alien -- pointer to an envvec struct
alist) ; Corresponding alist alist) ; Corresponding alist
;;; TODO Give it a finaliser that uses free() to release the envvec struct.
;;; TODO Maintain alist ;;; Once more, Olin's define-record is not sufficient
(define (make-environ c-struct alist)
(let ((env (make-env c-struct alist)))
(add-finalizer! env env-finalizer)
env))
(define (env-finalizer env)
(display "freeing env")
(%free-env (env:c-struct env)))
(define env-lock (make-lock)) (define env-lock (make-lock))
(define (obtain-env-lock) (obtain-lock env-lock)) ; Thunks for (define (obtain-env-lock) (obtain-lock env-lock)) ; Thunks for
@ -134,7 +142,7 @@
(%align-env (env:c-struct (current-env)))) (%align-env (env:c-struct (current-env))))
(define (make-threads-env alist) (define (make-threads-env alist)
(make-env (alist->envvec alist) alist)) (make-environ (alist->envvec alist) alist))
(define (current-env) (fluid $current-env)) (define (current-env) (fluid $current-env))
@ -169,24 +177,33 @@
(define (alist->env alist) (define (alist->env alist)
(with-env-aligned* (with-env-aligned*
(lambda () (lambda ()
(envvec-alist->env alist)))) (let ((env (current-env)))
(envvec-alist->env alist)
(set-env:alist env alist)))))
(define (delete-env name) (define (delete-env name)
(with-env-aligned* (let ((env (current-env)))
(lambda () (set-env:alist env (alist-delete name (env:alist env))))
(envvec-delete-env name)))) (envvec-delete-env name))
(define (setenv name value) (define (setenv name value)
(with-env-aligned* (with-env-aligned*
(lambda () (lambda ()
(if name (if value
(envvec-setenv name value) (begin
(envvec-delete-env name))))) (envvec-setenv name value)
(let ((env (current-env)))
(set-env:alist env (alist-update name value (env:alist env)))))
(delete-env name)))))
(define (getenv name) (define (getenv name)
(with-env-aligned* (with-env-aligned*
(lambda () (lambda ()
(envvec-getenv name)))) (let* ((here (assoc name (env:alist (current-env))))
(here (if here (cdr here) here)))
(if (not (equal? here (envvec-getenv name)))
(error "not equal" here (envvec-getenv name))
here)))))
;;; These two functions are obsoleted by the more general INFIX-SPLITTER and ;;; These two functions are obsoleted by the more general INFIX-SPLITTER and
@ -269,6 +286,8 @@
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;; working directory per thread ;;; working directory per thread
;;; this reflects the cwd of the process
(define-record cache (define-record cache
cwd) cwd)
@ -276,18 +295,52 @@
(lambda (cache) (lambda (cache)
(set-cache:cwd cache ""))) ; set the cache to an impossible filename. (set-cache:cwd cache ""))) ; set the cache to an impossible filename.
(define unix-cwd (define *unix-cwd*
(make-cache "")) ; Initialise the cache to an impossible filename. (make-cache "")) ; Initialise the cache to an impossible filename.
(define cwd-lock (make-lock)) (define (unix-cwd)
(define (obtain-cwd-lock) (obtain-lock cwd-lock)) ; Thunks for (cache:cwd *unix-cwd*))
(define (release-cwd-lock) (release-lock cwd-lock)) ; DYNAMIC-WINDs.
;;; The thread-specific CWD. (define cwd-lock (make-lock))
;;; Actually do the syscall and update the cache
;;; assumes the cwd lock obtained
(define (chdir-and-cache dir)
(process-chdir dir)
(set-cache:cwd *unix-cwd* (process-cwd)))
;;; Dynamic-wind is not the rigth thing to take care of the lock;
;;; it would release the lock on every context switch.
;;; With-lock releases the lock on a condition, using call/cc will
;;; skrew things up
;;; Should be moved somewhere else
(define (with-lock lock thunk)
(with-handler (lambda (condition more)
(release-lock lock)
(more))
(lambda ()
(obtain-lock lock)
(let ((result (thunk)))
(release-lock lock)
result))))
;;; The thread-specific CWD: A fluid
(define $cwd (make-fluid (process-cwd))) (define $cwd (make-fluid (process-cwd)))
(define (cwd) (fluid $cwd)) (define (cwd) (fluid $cwd))
(define (with-cwd* dir thunk) (let-fluid $cwd dir thunk))
(define (set-cwd! dir) (set-fluid! $cwd dir)) (define (set-cwd! dir) (set-fluid! $cwd dir))
(define (let-cwd dir thunk)
(let-fluid $cwd dir thunk))
(define (with-cwd* dir thunk)
(let ((changed-dir #f))
(with-lock cwd-lock
(lambda ()
(align-cwd!)
(chdir-and-cache dir)
(set! changed-dir (unix-cwd))))
(let-cwd changed-dir thunk)))
;; Align the Unix CWD with the scsh CWD. ;; Align the Unix CWD with the scsh CWD.
;; Since another thread could disalign, this call and ;; Since another thread could disalign, this call and
@ -296,16 +349,16 @@
(define (align-cwd!) (define (align-cwd!)
(let ((dir (cwd))) (let ((dir (cwd)))
(if (not (string=? (cwd) (cache:cwd unix-cwd))) (if (not (string=? dir (unix-cwd)))
(begin (process-chdir dir) (chdir-and-cache dir))))
(set-cache:cwd unix-cwd dir)))))
(define (chdir dir) (define (chdir dir)
(dynamic-wind obtain-cwd-lock (with-lock cwd-lock
(lambda () (lambda ()
(process-chdir dir) (align-cwd!)
(set-cwd! (process-cwd))) (chdir-and-cache dir)
release-cwd-lock)) (set-cwd! (unix-cwd)))))
;;; For thunks that don't raise exceptions or throw to continuations, ;;; For thunks that don't raise exceptions or throw to continuations,
;;; this is overkill & probably a little heavyweight for frequent use. ;;; this is overkill & probably a little heavyweight for frequent use.
@ -319,9 +372,11 @@
;;; the syscall, turn them back on. ;;; the syscall, turn them back on.
(define (with-cwd-aligned* thunk) (define (with-cwd-aligned* thunk)
(dynamic-wind obtain-cwd-lock (dynamic-wind (lambda ()
(lambda () (dynamic-wind align-cwd! thunk values)) (with-lock cwd-lock
release-cwd-lock)) align-cwd!))
thunk
values))
;;; example syscall ;;; example syscall
;;; (define (exported-delete-file fname) ;;; (define (exported-delete-file fname)