Changeset c76bd34 for libcfa/src/concurrency
- Timestamp:
- Oct 7, 2020, 4:31:43 PM (4 years ago)
- Branches:
- ADT, arm-eh, ast-experimental, enum, forall-pointer-decay, jacob/cs343-translation, master, new-ast-unique-expr, pthread-emulation, qualifiedEnum
- Children:
- 848439f
- Parents:
- ae2c27a (diff), 597c5d18 (diff)
Note: this is a merge changeset, the changes displayed below correspond to the merge itself.
Use the(diff)
links above to see all the changes relative to each parent. - Location:
- libcfa/src/concurrency
- Files:
-
- 3 added
- 22 edited
Legend:
- Unmodified
- Added
- Removed
-
libcfa/src/concurrency/CtxSwitch-i386.S
rae2c27a rc76bd34 10 10 // Created On : Tue Dec 6 12:27:26 2016 11 11 // Last Modified By : Peter A. Buhr 12 // Last Modified On : Sun Aug 16 08:46:22202013 // Update Count : 412 // Last Modified On : Sun Sep 6 18:23:37 2020 13 // Update Count : 5 14 14 // 15 15 … … 35 35 36 36 // Copy the "from" context argument from the stack to register eax 37 // Return address is at 0(%esp), with parameters following 37 // Return address is at 0(%esp), with parameters following. 38 38 39 39 movl 4(%esp),%eax … … 50 50 movl %ebp,FP_OFFSET(%eax) 51 51 52 // Copy the "to" context argument from the stack to register eax 53 // Having pushed three words (= 12 bytes) on the stack, the54 // argument is now at 8 + 12 = 20(%esp)52 // Copy the "to" context argument from the stack to register eax. Having 53 // pushed 3 words (= 12 bytes) on the stack, the argument is now at 54 // 8 + 12 = 20(%esp). 55 55 56 56 movl 20(%esp),%eax -
libcfa/src/concurrency/alarm.cfa
rae2c27a rc76bd34 130 130 131 131 register_self( &node ); 132 park( __cfaabi_dbg_ctx);132 park(); 133 133 134 134 /* paranoid */ verify( !node.set ); -
libcfa/src/concurrency/coroutine.cfa
rae2c27a rc76bd34 47 47 48 48 //----------------------------------------------------------------------------- 49 FORALL_DATA_INSTANCE(CoroutineCancelled, 50 (dtype coroutine_t | sized(coroutine_t)), (coroutine_t)) 51 52 struct __cfaehm_node { 53 struct _Unwind_Exception unwind_exception; 54 struct __cfaehm_node * next; 55 int handler_index; 56 }; 57 58 forall(dtype T) 59 void mark_exception(CoroutineCancelled(T) *) {} 60 61 forall(dtype T | sized(T)) 62 void copy(CoroutineCancelled(T) * dst, CoroutineCancelled(T) * src) { 63 dst->the_coroutine = src->the_coroutine; 64 dst->the_exception = src->the_exception; 65 } 66 67 forall(dtype T) 68 const char * msg(CoroutineCancelled(T) *) { 69 return "CoroutineCancelled(...)"; 70 } 71 72 // This code should not be inlined. It is the error path on resume. 73 forall(dtype T | is_coroutine(T)) 74 void __cfaehm_cancelled_coroutine( T & cor, $coroutine * desc ) { 75 verify( desc->cancellation ); 76 desc->state = Cancelled; 77 exception_t * except = (exception_t *)(1 + (__cfaehm_node *)desc->cancellation); 78 79 CoroutineCancelled(T) except; 80 except.the_coroutine = &cor; 81 except.the_exception = except; 82 throwResume except; 83 84 except->virtual_table->free( except ); 85 free( desc->cancellation ); 86 desc->cancellation = 0p; 87 } 88 89 //----------------------------------------------------------------------------- 49 90 // Global state variables 50 91 … … 180 221 this->storage->limit = storage; 181 222 this->storage->base = (void*)((intptr_t)storage + size); 223 this->storage->exception_context.top_resume = 0p; 224 this->storage->exception_context.current_exception = 0p; 182 225 __attribute__((may_alias)) intptr_t * istorage = (intptr_t*)&this->storage; 183 226 *istorage |= userStack ? 0x1 : 0x0; -
libcfa/src/concurrency/coroutine.hfa
rae2c27a rc76bd34 18 18 #include <assert.h> 19 19 #include "invoke.h" 20 #include "../exception.hfa" 21 22 //----------------------------------------------------------------------------- 23 // Exception thrown from resume when a coroutine stack is cancelled. 24 // Should not have to be be sized (see trac #196). 25 FORALL_DATA_EXCEPTION(CoroutineCancelled, 26 (dtype coroutine_t | sized(coroutine_t)), (coroutine_t)) ( 27 coroutine_t * the_coroutine; 28 exception_t * the_exception; 29 ); 30 31 forall(dtype T) 32 void mark_exception(CoroutineCancelled(T) *); 33 34 forall(dtype T | sized(T)) 35 void copy(CoroutineCancelled(T) * dst, CoroutineCancelled(T) * src); 36 37 forall(dtype T) 38 const char * msg(CoroutineCancelled(T) *); 20 39 21 40 //----------------------------------------------------------------------------- … … 23 42 // Anything that implements this trait can be resumed. 24 43 // Anything that is resumed is a coroutine. 25 trait is_coroutine(dtype T) { 26 void main(T & this); 27 $coroutine * get_coroutine(T & this); 44 trait is_coroutine(dtype T | sized(T) 45 | is_resumption_exception(CoroutineCancelled(T)) 46 | VTABLE_ASSERTION(CoroutineCancelled, (T))) { 47 void main(T & this); 48 $coroutine * get_coroutine(T & this); 28 49 }; 29 50 … … 112 133 } 113 134 } 135 136 forall(dtype T | is_coroutine(T)) 137 void __cfaehm_cancelled_coroutine( T & cor, $coroutine * desc ); 114 138 115 139 // Resume implementation inlined for performance … … 145 169 // always done for performance testing 146 170 $ctx_switch( src, dst ); 171 if ( unlikely(dst->cancellation) ) { 172 __cfaehm_cancelled_coroutine( cor, dst ); 173 } 147 174 148 175 return cor; -
libcfa/src/concurrency/exception.cfa
rae2c27a rc76bd34 57 57 58 58 STOP_AT_END_FUNCTION(coroutine_cancelstop, 59 // TODO: Instead pass information to the last resumer. 59 struct $coroutine * src = ($coroutine *)stop_param; 60 struct $coroutine * dst = src->last; 61 62 $ctx_switch( src, dst ); 60 63 abort(); 61 64 ) -
libcfa/src/concurrency/exception.hfa
rae2c27a rc76bd34 18 18 #include "bits/defs.hfa" 19 19 #include "invoke.h" 20 struct _Unwind_Exception;21 22 // It must also be usable as a C header file.23 20 24 21 #ifdef __cforall 25 22 extern "C" { 23 24 #define HIDE_EXPORTS 26 25 #endif 26 #include "unwind.h" 27 27 28 28 struct exception_context_t * this_exception_context(void) OPTIONAL_THREAD; … … 32 32 33 33 #ifdef __cforall 34 #undef HIDE_EXPORTS 34 35 } 35 36 #endif -
libcfa/src/concurrency/invoke.h
rae2c27a rc76bd34 68 68 }; 69 69 70 enum __Coroutine_State { Halted, Start, Primed, Blocked, Ready, Active };70 enum __Coroutine_State { Halted, Start, Primed, Blocked, Ready, Active, Cancelled }; 71 71 72 72 struct $coroutine { … … 93 93 94 94 }; 95 // Wrapper for gdb 96 struct cfathread_coroutine_t { struct $coroutine debug; }; 95 97 96 98 static inline struct __stack_t * __get_stack( struct $coroutine * cor ) { … … 129 131 struct __condition_node_t * dtor_node; 130 132 }; 133 // Wrapper for gdb 134 struct cfathread_monitor_t { struct $monitor debug; }; 131 135 132 136 struct __monitor_group_t { … … 186 190 } node; 187 191 188 #ifdef __CFA_DEBUG__ 189 // previous function to park/unpark the thread 190 const char * park_caller; 191 int park_result; 192 enum __Coroutine_State park_state; 193 bool park_stale; 194 const char * unpark_caller; 195 int unpark_result; 196 enum __Coroutine_State unpark_state; 197 bool unpark_stale; 192 #if defined( __CFA_WITH_VERIFY__ ) 193 unsigned long long canary; 198 194 #endif 199 195 }; 196 // Wrapper for gdb 197 struct cfathread_thread_t { struct $thread debug; }; 200 198 201 199 #ifdef __CFA_DEBUG__ -
libcfa/src/concurrency/io.cfa
rae2c27a rc76bd34 69 69 if( block ) { 70 70 enable_interrupts( __cfaabi_dbg_ctx ); 71 park( __cfaabi_dbg_ctx);71 park(); 72 72 disable_interrupts(); 73 73 } … … 97 97 98 98 if(nextt) { 99 unpark( nextt __cfaabi_dbg_ctx2);99 unpark( nextt ); 100 100 enable_interrupts( __cfaabi_dbg_ctx ); 101 101 return true; … … 159 159 160 160 static inline void process(struct io_uring_cqe & cqe ) { 161 struct __io_user_data_t * data = (struct __io_user_data_t *)(uintptr_t)cqe.user_data; 162 __cfadbg_print_safe( io, "Kernel I/O : Syscall completed : cqe %p, result %d for %p\n", data, cqe.res, data->thrd ); 163 164 data->result = cqe.res; 165 post( data->sem ); 161 struct io_future_t * future = (struct io_future_t *)(uintptr_t)cqe.user_data; 162 __cfadbg_print_safe( io, "Kernel I/O : Syscall completed : cqe %p, result %d for %p\n", future, cqe.res, data->thrd ); 163 164 fulfil( *future, cqe.res ); 166 165 } 167 166 -
libcfa/src/concurrency/io/setup.cfa
rae2c27a rc76bd34 147 147 static void * iopoll_loop( __attribute__((unused)) void * args ) { 148 148 __processor_id_t id; 149 id.full_proc = false; 149 150 id.id = doregister(&id); 150 151 __cfaabi_dbg_print_safe( "Kernel : IO poller thread starting\n" ); … … 246 247 thrd.link.next = 0p; 247 248 thrd.link.prev = 0p; 248 __cfaabi_dbg_debug_do( thrd.unpark_stale = true );249 249 250 250 // Fixup the thread state … … 266 266 267 267 // unpark the fast io_poller 268 unpark( &thrd __cfaabi_dbg_ctx2);268 unpark( &thrd ); 269 269 } 270 270 else { … … 275 275 } 276 276 } else { 277 unpark( &thrd __cfaabi_dbg_ctx2);277 unpark( &thrd ); 278 278 } 279 279 -
libcfa/src/concurrency/io/types.hfa
rae2c27a rc76bd34 16 16 #pragma once 17 17 18 extern "C" { 19 #include <linux/types.h> 20 } 21 22 #include "bits/locks.hfa" 23 18 24 #if defined(CFA_HAVE_LINUX_IO_URING_H) 19 extern "C" {20 #include <linux/types.h>21 }22 23 #include "bits/locks.hfa"24 25 25 #define LEADER_LOCK 26 26 struct __leaderlock_t { … … 101 101 }; 102 102 103 104 //-----------------------------------------------------------------------105 // IO user data106 struct __io_user_data_t {107 __s32 result;108 oneshot sem;109 };110 111 103 //----------------------------------------------------------------------- 112 104 // Misc … … 143 135 void __ioctx_prepare_block($io_ctx_thread & ctx, struct epoll_event & ev); 144 136 #endif 137 138 //----------------------------------------------------------------------- 139 // IO user data 140 struct io_future_t { 141 future_t self; 142 __s32 result; 143 }; 144 145 static inline { 146 bool fulfil( io_future_t & this, __s32 result ) { 147 this.result = result; 148 return fulfil(this.self); 149 } 150 151 // Wait for the future to be fulfilled 152 bool wait( io_future_t & this ) { 153 return wait(this.self); 154 } 155 } -
libcfa/src/concurrency/iofwd.hfa
rae2c27a rc76bd34 40 40 41 41 struct cluster; 42 struct io_future_t; 42 43 struct io_context; 43 44 struct io_cancellation; … … 48 49 struct statx; 49 50 50 extern ssize_t cfa_preadv2(int fd, const struct iovec *iov, int iovcnt, off_t offset, int flags, int submit_flags = 0, Duration timeout = -1`s, io_cancellation * cancellation = 0p, io_context * context = 0p); 51 extern ssize_t cfa_pwritev2(int fd, const struct iovec *iov, int iovcnt, off_t offset, int flags, int submit_flags = 0, Duration timeout = -1`s, io_cancellation * cancellation = 0p, io_context * context = 0p); 52 extern int cfa_fsync(int fd, int submit_flags = 0, Duration timeout = -1`s, io_cancellation * cancellation = 0p, io_context * context = 0p); 53 extern int cfa_sync_file_range(int fd, int64_t offset, int64_t nbytes, unsigned int flags, int submit_flags = 0, Duration timeout = -1`s, io_cancellation * cancellation = 0p, io_context * context = 0p); 54 extern ssize_t cfa_sendmsg(int sockfd, const struct msghdr *msg, int flags, int submit_flags = 0, Duration timeout = -1`s, io_cancellation * cancellation = 0p, io_context * context = 0p); 55 extern ssize_t cfa_recvmsg(int sockfd, struct msghdr *msg, int flags, int submit_flags = 0, Duration timeout = -1`s, io_cancellation * cancellation = 0p, io_context * context = 0p); 56 extern ssize_t cfa_send(int sockfd, const void *buf, size_t len, int flags, int submit_flags = 0, Duration timeout = -1`s, io_cancellation * cancellation = 0p, io_context * context = 0p); 57 extern ssize_t cfa_recv(int sockfd, void *buf, size_t len, int flags, int submit_flags = 0, Duration timeout = -1`s, io_cancellation * cancellation = 0p, io_context * context = 0p); 58 extern int cfa_accept4(int sockfd, struct sockaddr *addr, socklen_t *addrlen, int flags, int submit_flags = 0, Duration timeout = -1`s, io_cancellation * cancellation = 0p, io_context * context = 0p); 59 extern int cfa_connect(int sockfd, const struct sockaddr *addr, socklen_t addrlen, int submit_flags = 0, Duration timeout = -1`s, io_cancellation * cancellation = 0p, io_context * context = 0p); 60 extern int cfa_fallocate(int fd, int mode, uint64_t offset, uint64_t len, int submit_flags = 0, Duration timeout = -1`s, io_cancellation * cancellation = 0p, io_context * context = 0p); 61 extern int cfa_fadvise(int fd, uint64_t offset, uint64_t len, int advice, int submit_flags = 0, Duration timeout = -1`s, io_cancellation * cancellation = 0p, io_context * context = 0p); 62 extern int cfa_madvise(void *addr, size_t length, int advice, int submit_flags = 0, Duration timeout = -1`s, io_cancellation * cancellation = 0p, io_context * context = 0p); 63 extern int cfa_openat(int dirfd, const char *pathname, int flags, mode_t mode, int submit_flags = 0, Duration timeout = -1`s, io_cancellation * cancellation = 0p, io_context * context = 0p); 64 extern int cfa_close(int fd, int submit_flags = 0, Duration timeout = -1`s, io_cancellation * cancellation = 0p, io_context * context = 0p); 65 extern int cfa_statx(int dirfd, const char *pathname, int flags, unsigned int mask, struct statx *statxbuf, int submit_flags = 0, Duration timeout = -1`s, io_cancellation * cancellation = 0p, io_context * context = 0p); 66 extern ssize_t cfa_read(int fd, void *buf, size_t count, int submit_flags = 0, Duration timeout = -1`s, io_cancellation * cancellation = 0p, io_context * context = 0p); 67 extern ssize_t cfa_write(int fd, void *buf, size_t count, int submit_flags = 0, Duration timeout = -1`s, io_cancellation * cancellation = 0p, io_context * context = 0p); 68 extern ssize_t cfa_splice(int fd_in, loff_t *off_in, int fd_out, loff_t *off_out, size_t len, unsigned int flags, int submit_flags = 0, Duration timeout = -1`s, io_cancellation * cancellation = 0p, io_context * context = 0p); 69 extern ssize_t cfa_tee(int fd_in, int fd_out, size_t len, unsigned int flags, int submit_flags = 0, Duration timeout = -1`s, io_cancellation * cancellation = 0p, io_context * context = 0p); 51 //---------- 52 // synchronous calls 53 #if defined(CFA_HAVE_PREADV2) 54 extern ssize_t cfa_preadv2(int fd, const struct iovec *iov, int iovcnt, off_t offset, int flags, int submit_flags, Duration timeout, io_cancellation * cancellation, io_context * context); 55 #endif 56 #if defined(CFA_HAVE_PWRITEV2) 57 extern ssize_t cfa_pwritev2(int fd, const struct iovec *iov, int iovcnt, off_t offset, int flags, int submit_flags, Duration timeout, io_cancellation * cancellation, io_context * context); 58 #endif 59 extern int cfa_fsync(int fd, int submit_flags, Duration timeout, io_cancellation * cancellation, io_context * context); 60 extern int cfa_epoll_ctl(int epfd, int op, int fd, struct epoll_event *event, int submit_flags, Duration timeout, io_cancellation * cancellation, io_context * context); 61 extern int cfa_sync_file_range(int fd, off64_t offset, off64_t nbytes, unsigned int flags, int submit_flags, Duration timeout, io_cancellation * cancellation, io_context * context); 62 extern ssize_t cfa_sendmsg(int sockfd, const struct msghdr *msg, int flags, int submit_flags, Duration timeout, io_cancellation * cancellation, io_context * context); 63 extern ssize_t cfa_recvmsg(int sockfd, struct msghdr *msg, int flags, int submit_flags, Duration timeout, io_cancellation * cancellation, io_context * context); 64 extern ssize_t cfa_send(int sockfd, const void *buf, size_t len, int flags, int submit_flags, Duration timeout, io_cancellation * cancellation, io_context * context); 65 extern ssize_t cfa_recv(int sockfd, void *buf, size_t len, int flags, int submit_flags, Duration timeout, io_cancellation * cancellation, io_context * context); 66 extern int cfa_accept4(int sockfd, struct sockaddr *addr, socklen_t *addrlen, int flags, int submit_flags, Duration timeout, io_cancellation * cancellation, io_context * context); 67 extern int cfa_connect(int sockfd, const struct sockaddr *addr, socklen_t addrlen, int submit_flags, Duration timeout, io_cancellation * cancellation, io_context * context); 68 extern int cfa_fallocate(int fd, int mode, off_t offset, off_t len, int submit_flags, Duration timeout, io_cancellation * cancellation, io_context * context); 69 extern int cfa_posix_fadvise(int fd, off_t offset, off_t len, int advice, int submit_flags, Duration timeout, io_cancellation * cancellation, io_context * context); 70 extern int cfa_madvise(void *addr, size_t length, int advice, int submit_flags, Duration timeout, io_cancellation * cancellation, io_context * context); 71 extern int cfa_openat(int dirfd, const char *pathname, int flags, mode_t mode, int submit_flags, Duration timeout, io_cancellation * cancellation, io_context * context); 72 #if defined(CFA_HAVE_OPENAT2) 73 extern int cfa_openat2(int dirfd, const char *pathname, struct open_how * how, size_t size, int submit_flags, Duration timeout, io_cancellation * cancellation, io_context * context); 74 #endif 75 extern int cfa_close(int fd, int submit_flags, Duration timeout, io_cancellation * cancellation, io_context * context); 76 #if defined(CFA_HAVE_STATX) 77 extern int cfa_statx(int dirfd, const char *pathname, int flags, unsigned int mask, struct statx *statxbuf, int submit_flags, Duration timeout, io_cancellation * cancellation, io_context * context); 78 #endif 79 extern ssize_t cfa_read(int fd, void * buf, size_t count, int submit_flags, Duration timeout, io_cancellation * cancellation, io_context * context); 80 extern ssize_t cfa_write(int fd, void * buf, size_t count, int submit_flags, Duration timeout, io_cancellation * cancellation, io_context * context); 81 extern ssize_t cfa_splice(int fd_in, loff_t *off_in, int fd_out, loff_t *off_out, size_t len, unsigned int flags, int submit_flags, Duration timeout, io_cancellation * cancellation, io_context * context); 82 extern ssize_t cfa_tee(int fd_in, int fd_out, size_t len, unsigned int flags, int submit_flags, Duration timeout, io_cancellation * cancellation, io_context * context); 83 84 //---------- 85 // asynchronous calls 86 #if defined(CFA_HAVE_PREADV2) 87 extern void async_preadv2(io_future_t & future, int fd, const struct iovec *iov, int iovcnt, off_t offset, int flags, int submit_flags, io_cancellation * cancellation, io_context * context); 88 #endif 89 #if defined(CFA_HAVE_PWRITEV2) 90 extern void async_pwritev2(io_future_t & future, int fd, const struct iovec *iov, int iovcnt, off_t offset, int flags, int submit_flags, io_cancellation * cancellation, io_context * context); 91 #endif 92 extern void async_fsync(io_future_t & future, int fd, int submit_flags, io_cancellation * cancellation, io_context * context); 93 extern void async_epoll_ctl(io_future_t & future, int epfd, int op, int fd, struct epoll_event *event, int submit_flags, io_cancellation * cancellation, io_context * context); 94 extern void async_sync_file_range(io_future_t & future, int fd, off64_t offset, off64_t nbytes, unsigned int flags, int submit_flags, io_cancellation * cancellation, io_context * context); 95 extern void async_sendmsg(io_future_t & future, int sockfd, const struct msghdr *msg, int flags, int submit_flags, io_cancellation * cancellation, io_context * context); 96 extern void async_recvmsg(io_future_t & future, int sockfd, struct msghdr *msg, int flags, int submit_flags, io_cancellation * cancellation, io_context * context); 97 extern void async_send(io_future_t & future, int sockfd, const void *buf, size_t len, int flags, int submit_flags, io_cancellation * cancellation, io_context * context); 98 extern void async_recv(io_future_t & future, int sockfd, void *buf, size_t len, int flags, int submit_flags, io_cancellation * cancellation, io_context * context); 99 extern void async_accept4(io_future_t & future, int sockfd, struct sockaddr *addr, socklen_t *addrlen, int flags, int submit_flags, io_cancellation * cancellation, io_context * context); 100 extern void async_connect(io_future_t & future, int sockfd, const struct sockaddr *addr, socklen_t addrlen, int submit_flags, io_cancellation * cancellation, io_context * context); 101 extern void async_fallocate(io_future_t & future, int fd, int mode, off_t offset, off_t len, int submit_flags, io_cancellation * cancellation, io_context * context); 102 extern void async_posix_fadvise(io_future_t & future, int fd, off_t offset, off_t len, int advice, int submit_flags, io_cancellation * cancellation, io_context * context); 103 extern void async_madvise(io_future_t & future, void *addr, size_t length, int advice, int submit_flags, io_cancellation * cancellation, io_context * context); 104 extern void async_openat(io_future_t & future, int dirfd, const char *pathname, int flags, mode_t mode, int submit_flags, io_cancellation * cancellation, io_context * context); 105 #if defined(CFA_HAVE_OPENAT2) 106 extern void async_openat2(io_future_t & future, int dirfd, const char *pathname, struct open_how * how, size_t size, int submit_flags, io_cancellation * cancellation, io_context * context); 107 #endif 108 extern void async_close(io_future_t & future, int fd, int submit_flags, io_cancellation * cancellation, io_context * context); 109 #if defined(CFA_HAVE_STATX) 110 extern void async_statx(io_future_t & future, int dirfd, const char *pathname, int flags, unsigned int mask, struct statx *statxbuf, int submit_flags, io_cancellation * cancellation, io_context * context); 111 #endif 112 void async_read(io_future_t & future, int fd, void * buf, size_t count, int submit_flags, io_cancellation * cancellation, io_context * context); 113 extern void async_write(io_future_t & future, int fd, void * buf, size_t count, int submit_flags, io_cancellation * cancellation, io_context * context); 114 extern void async_splice(io_future_t & future, int fd_in, loff_t *off_in, int fd_out, loff_t *off_out, size_t len, unsigned int flags, int submit_flags, io_cancellation * cancellation, io_context * context); 115 extern void async_tee(io_future_t & future, int fd_in, int fd_out, size_t len, unsigned int flags, int submit_flags, io_cancellation * cancellation, io_context * context); 116 70 117 71 118 //----------------------------------------------------------------------------- -
libcfa/src/concurrency/kernel.cfa
rae2c27a rc76bd34 237 237 $coroutine * proc_cor = get_coroutine(this->runner); 238 238 239 // Update global state240 kernelTLS.this_thread = thrd_dst;241 242 239 // set state of processor coroutine to inactive 243 240 verify(proc_cor->state == Active); … … 249 246 thrd_dst->state = Active; 250 247 251 __cfaabi_dbg_debug_do( 252 thrd_dst->park_stale = true; 253 thrd_dst->unpark_stale = true; 254 ) 248 // Update global state 249 kernelTLS.this_thread = thrd_dst; 255 250 256 251 /* paranoid */ verify( ! kernelTLS.preemption_state.enabled ); 257 252 /* paranoid */ verify( kernelTLS.this_thread == thrd_dst ); 253 /* paranoid */ verify( thrd_dst->context.SP ); 258 254 /* paranoid */ verifyf( ((uintptr_t)thrd_dst->context.SP) < ((uintptr_t)__get_stack(thrd_dst->curr_cor)->base ) || thrd_dst->curr_cor == proc_cor, "ERROR : Destination $thread %p has been corrupted.\n StackPointer too small.\n", thrd_dst ); // add escape condition if we are setting up the processor 259 255 /* paranoid */ verifyf( ((uintptr_t)thrd_dst->context.SP) > ((uintptr_t)__get_stack(thrd_dst->curr_cor)->limit) || thrd_dst->curr_cor == proc_cor, "ERROR : Destination $thread %p has been corrupted.\n StackPointer too large.\n", thrd_dst ); // add escape condition if we are setting up the processor 256 /* paranoid */ verify( 0x0D15EA5E0D15EA5E == thrd_dst->canary ); 257 258 260 259 261 260 // set context switch to the thread that the processor is executing 262 verify( thrd_dst->context.SP );263 261 __cfactx_switch( &proc_cor->context, &thrd_dst->context ); 264 262 // when __cfactx_switch returns we are back in the processor coroutine 265 263 264 /* paranoid */ verify( 0x0D15EA5E0D15EA5E == thrd_dst->canary ); 266 265 /* paranoid */ verifyf( ((uintptr_t)thrd_dst->context.SP) > ((uintptr_t)__get_stack(thrd_dst->curr_cor)->limit), "ERROR : Destination $thread %p has been corrupted.\n StackPointer too large.\n", thrd_dst ); 267 266 /* paranoid */ verifyf( ((uintptr_t)thrd_dst->context.SP) < ((uintptr_t)__get_stack(thrd_dst->curr_cor)->base ), "ERROR : Destination $thread %p has been corrupted.\n StackPointer too small.\n", thrd_dst ); 267 /* paranoid */ verify( thrd_dst->context.SP ); 268 268 /* paranoid */ verify( kernelTLS.this_thread == thrd_dst ); 269 269 /* paranoid */ verify( ! kernelTLS.preemption_state.enabled ); 270 270 271 // Reset global state 272 kernelTLS.this_thread = 0p; 271 273 272 274 // We just finished running a thread, there are a few things that could have happened. … … 286 288 // The thread has halted, it should never be scheduled/run again 287 289 // We may need to wake someone up here since 288 unpark( this->destroyer __cfaabi_dbg_ctx2);290 unpark( this->destroyer ); 289 291 this->destroyer = 0p; 290 292 break RUNNING; … … 296 298 // set state of processor coroutine to active and the thread to inactive 297 299 int old_ticket = __atomic_fetch_sub(&thrd_dst->ticket, 1, __ATOMIC_SEQ_CST); 298 __cfaabi_dbg_debug_do( thrd_dst->park_result = old_ticket; )299 300 switch(old_ticket) { 300 301 case 1: … … 313 314 // Just before returning to the processor, set the processor coroutine to active 314 315 proc_cor->state = Active; 315 kernelTLS.this_thread = 0p;316 316 317 317 /* paranoid */ verify( ! kernelTLS.preemption_state.enabled ); … … 334 334 __x87_store; 335 335 #endif 336 verify( proc_cor->context.SP ); 336 /* paranoid */ verify( proc_cor->context.SP ); 337 /* paranoid */ verify( 0x0D15EA5E0D15EA5E == thrd_src->canary ); 337 338 __cfactx_switch( &thrd_src->context, &proc_cor->context ); 339 /* paranoid */ verify( 0x0D15EA5E0D15EA5E == thrd_src->canary ); 338 340 #if defined( __i386 ) || defined( __x86_64 ) 339 341 __x87_load; … … 367 369 /* paranoid */ #endif 368 370 /* paranoid */ verifyf( thrd->link.next == 0p, "Expected null got %p", thrd->link.next ); 371 /* paranoid */ verify( 0x0D15EA5E0D15EA5E == thrd->canary ); 372 369 373 370 374 if (thrd->preempted == __NO_PREEMPTION) thrd->state = Ready; … … 403 407 404 408 // KERNEL ONLY unpark with out disabling interrupts 405 void __unpark( struct __processor_id_t * id, $thread * thrd __cfaabi_dbg_ctx_param2 ) { 406 // record activity 407 __cfaabi_dbg_record_thrd( *thrd, false, caller ); 408 409 void __unpark( struct __processor_id_t * id, $thread * thrd ) { 409 410 int old_ticket = __atomic_fetch_add(&thrd->ticket, 1, __ATOMIC_SEQ_CST); 410 __cfaabi_dbg_debug_do( thrd->unpark_result = old_ticket; thrd->unpark_state = thrd->state; )411 411 switch(old_ticket) { 412 412 case 1: … … 426 426 } 427 427 428 void unpark( $thread * thrd __cfaabi_dbg_ctx_param2) {428 void unpark( $thread * thrd ) { 429 429 if( !thrd ) return; 430 430 431 431 disable_interrupts(); 432 __unpark( (__processor_id_t*)kernelTLS.this_processor, thrd __cfaabi_dbg_ctx_fwd2);432 __unpark( (__processor_id_t*)kernelTLS.this_processor, thrd ); 433 433 enable_interrupts( __cfaabi_dbg_ctx ); 434 434 } 435 435 436 void park( __cfaabi_dbg_ctx_param) {436 void park( void ) { 437 437 /* paranoid */ verify( kernelTLS.preemption_state.enabled ); 438 438 disable_interrupts(); 439 439 /* paranoid */ verify( ! kernelTLS.preemption_state.enabled ); 440 440 /* paranoid */ verify( kernelTLS.this_thread->preempted == __NO_PREEMPTION ); 441 442 // record activity443 __cfaabi_dbg_record_thrd( *kernelTLS.this_thread, true, caller );444 441 445 442 returnToKernel(); … … 521 518 disable_interrupts(); 522 519 /* paranoid */ verify( ! kernelTLS.preemption_state.enabled ); 523 bool ret =post( this->idle );520 post( this->idle ); 524 521 enable_interrupts( __cfaabi_dbg_ctx ); 525 522 } … … 649 646 // atomically release spin lock and block 650 647 unlock( lock ); 651 park( __cfaabi_dbg_ctx);648 park(); 652 649 return true; 653 650 } … … 670 667 671 668 // make new owner 672 unpark( thrd __cfaabi_dbg_ctx2);669 unpark( thrd ); 673 670 674 671 return thrd != 0p; … … 681 678 count += diff; 682 679 for(release) { 683 unpark( pop_head( waiting ) __cfaabi_dbg_ctx2);680 unpark( pop_head( waiting ) ); 684 681 } 685 682 … … 697 694 this.prev_thrd = kernelTLS.this_thread; 698 695 } 699 700 void __cfaabi_dbg_record_thrd($thread & this, bool park, const char prev_name[]) {701 if(park) {702 this.park_caller = prev_name;703 this.park_stale = false;704 }705 else {706 this.unpark_caller = prev_name;707 this.unpark_stale = false;708 }709 }710 696 } 711 697 ) -
libcfa/src/concurrency/kernel.hfa
rae2c27a rc76bd34 23 23 24 24 extern "C" { 25 #include <bits/pthreadtypes.h> 25 #include <bits/pthreadtypes.h> 26 #include <linux/types.h> 26 27 } 27 28 … … 47 48 // Processor id, required for scheduling threads 48 49 struct __processor_id_t { 49 unsigned id; 50 unsigned id:24; 51 bool full_proc:1; 50 52 51 53 #if !defined(__CFA_NO_STATISTICS__) … … 157 159 158 160 struct io_cancellation { 159 uint32_ttarget;161 __u64 target; 160 162 }; 161 163 -
libcfa/src/concurrency/kernel/fwd.hfa
rae2c27a rc76bd34 118 118 119 119 extern "Cforall" { 120 extern void park( __cfaabi_dbg_ctx_param);121 extern void unpark( struct $thread * this __cfaabi_dbg_ctx_param2);120 extern void park( void ); 121 extern void unpark( struct $thread * this ); 122 122 static inline struct $thread * active_thread () { return TL_GET( this_thread ); } 123 123 -
libcfa/src/concurrency/kernel/startup.cfa
rae2c27a rc76bd34 451 451 link.next = 0p; 452 452 link.prev = 0p; 453 #if defined( __CFA_WITH_VERIFY__ ) 454 canary = 0x0D15EA5E0D15EA5E; 455 #endif 453 456 454 457 node.next = 0p; … … 470 473 this.name = name; 471 474 this.cltr = &_cltr; 472 id = -1u;475 full_proc = true; 473 476 destroyer = 0p; 474 477 do_terminate = false; -
libcfa/src/concurrency/kernel_private.hfa
rae2c27a rc76bd34 64 64 65 65 // KERNEL ONLY unpark with out disabling interrupts 66 void __unpark( struct __processor_id_t *, $thread * thrd __cfaabi_dbg_ctx_param2);66 void __unpark( struct __processor_id_t *, $thread * thrd ); 67 67 68 68 static inline bool __post(single_sem & this, struct __processor_id_t * id) { … … 77 77 else { 78 78 if(__atomic_compare_exchange_n(&this.ptr, &expected, 0p, false, __ATOMIC_SEQ_CST, __ATOMIC_SEQ_CST)) { 79 __unpark( id, expected __cfaabi_dbg_ctx2);79 __unpark( id, expected ); 80 80 return true; 81 81 } -
libcfa/src/concurrency/monitor.cfa
rae2c27a rc76bd34 89 89 __cfaabi_dbg_print_safe( "Kernel : %10p Entering mon %p (%p)\n", thrd, this, this->owner); 90 90 91 if( !this->owner ) { 91 if( unlikely(0 != (0x1 & (uintptr_t)this->owner)) ) { 92 abort( "Attempt by thread \"%.256s\" (%p) to access joined monitor %p.", thrd->self_cor.name, thrd, this ); 93 } 94 else if( !this->owner ) { 92 95 // No one has the monitor, just take it 93 96 __set_owner( this, thrd ); … … 119 122 120 123 unlock( this->lock ); 121 park( __cfaabi_dbg_ctx);124 park(); 122 125 123 126 __cfaabi_dbg_print_safe( "Kernel : %10p Entered mon %p\n", thrd, this); … … 137 140 } 138 141 139 static void __dtor_enter( $monitor * this, fptr_t func ) {142 static void __dtor_enter( $monitor * this, fptr_t func, bool join ) { 140 143 // Lock the monitor spinlock 141 144 lock( this->lock __cfaabi_dbg_ctx2 ); … … 157 160 return; 158 161 } 159 else if( this->owner == thrd ) {162 else if( this->owner == thrd && !join) { 160 163 // We already have the monitor... but where about to destroy it so the nesting will fail 161 164 // Abort! 162 165 abort( "Attempt to destroy monitor %p by thread \"%.256s\" (%p) in nested mutex.", this, thrd->self_cor.name, thrd ); 166 } 167 // SKULLDUGGERY: join will act as a dtor so it would normally trigger to above check 168 // to avoid that it sets the owner to the special value thrd | 1p before exiting 169 else if( this->owner == ($thread*)(1 | (uintptr_t)thrd) ) { 170 // restore the owner and just return 171 __cfaabi_dbg_print_safe( "Kernel : Destroying free mon %p\n", this); 172 173 // No one has the monitor, just take it 174 this->owner = thrd; 175 176 verifyf( kernelTLS.this_thread == this->owner, "Expected owner to be %p, got %p (r: %i, m: %p)", kernelTLS.this_thread, this->owner, this->recursion, this ); 177 178 unlock( this->lock ); 179 return; 163 180 } 164 181 … … 184 201 // Release the next thread 185 202 /* paranoid */ verifyf( urgent->owner->waiting_thread == this->owner, "Expected owner to be %p, got %p (r: %i, m: %p)", kernelTLS.this_thread, this->owner, this->recursion, this ); 186 unpark( urgent->owner->waiting_thread __cfaabi_dbg_ctx2);203 unpark( urgent->owner->waiting_thread ); 187 204 188 205 // Park current thread waiting 189 park( __cfaabi_dbg_ctx);206 park(); 190 207 191 208 // Some one was waiting for us, enter … … 205 222 206 223 // Park current thread waiting 207 park( __cfaabi_dbg_ctx);224 park(); 208 225 209 226 /* paranoid */ verifyf( kernelTLS.this_thread == this->owner, "Expected owner to be %p, got %p (r: %i, m: %p)", kernelTLS.this_thread, this->owner, this->recursion, this ); … … 247 264 //We need to wake-up the thread 248 265 /* paranoid */ verifyf( !new_owner || new_owner == this->owner, "Expected owner to be %p, got %p (m: %p)", new_owner, this->owner, this ); 249 unpark( new_owner __cfaabi_dbg_ctx2);266 unpark( new_owner ); 250 267 } 251 268 252 269 // Leave single monitor for the last time 253 void __dtor_leave( $monitor * this ) {270 void __dtor_leave( $monitor * this, bool join ) { 254 271 __cfaabi_dbg_debug_do( 255 272 if( TL_GET( this_thread ) != this->owner ) { 256 273 abort( "Destroyed monitor %p has inconsistent owner, expected %p got %p.\n", this, TL_GET( this_thread ), this->owner); 257 274 } 258 if( this->recursion != 1 ) {275 if( this->recursion != 1 && !join ) { 259 276 abort( "Destroyed monitor %p has %d outstanding nested calls.\n", this, this->recursion - 1); 260 277 } 261 278 ) 279 280 this->owner = ($thread*)(1 | (uintptr_t)this->owner); 262 281 } 263 282 … … 307 326 } 308 327 328 // Join a thread 329 forall( dtype T | is_thread(T) ) 330 T & join( T & this ) { 331 $monitor * m = get_monitor(this); 332 void (*dtor)(T& mutex this) = ^?{}; 333 monitor_dtor_guard_t __guard = { &m, (fptr_t)dtor, true }; 334 { 335 return this; 336 } 337 } 338 309 339 // Enter multiple monitor 310 340 // relies on the monitor array being sorted … … 366 396 // Ctor for monitor guard 367 397 // Sorts monitors before entering 368 void ?{}( monitor_dtor_guard_t & this, $monitor * m [], fptr_t func ) {398 void ?{}( monitor_dtor_guard_t & this, $monitor * m [], fptr_t func, bool join ) { 369 399 // optimization 370 400 $thread * thrd = TL_GET( this_thread ); … … 376 406 this.prev = thrd->monitors; 377 407 408 // Save whether we are in a join or not 409 this.join = join; 410 378 411 // Update thread context (needed for conditions) 379 412 (thrd->monitors){m, 1, func}; 380 413 381 __dtor_enter( this.m, func );414 __dtor_enter( this.m, func, join ); 382 415 } 383 416 … … 385 418 void ^?{}( monitor_dtor_guard_t & this ) { 386 419 // Leave the monitors in order 387 __dtor_leave( this.m );420 __dtor_leave( this.m, this.join ); 388 421 389 422 // Restore thread context … … 460 493 // Wake the threads 461 494 for(int i = 0; i < thread_count; i++) { 462 unpark( threads[i] __cfaabi_dbg_ctx2);495 unpark( threads[i] ); 463 496 } 464 497 465 498 // Everything is ready to go to sleep 466 park( __cfaabi_dbg_ctx);499 park(); 467 500 468 501 // We are back, restore the owners and recursions … … 542 575 543 576 // unpark the thread we signalled 544 unpark( signallee __cfaabi_dbg_ctx2);577 unpark( signallee ); 545 578 546 579 //Everything is ready to go to sleep 547 park( __cfaabi_dbg_ctx);580 park(); 548 581 549 582 … … 646 679 647 680 // unpark the thread we signalled 648 unpark( next __cfaabi_dbg_ctx2);681 unpark( next ); 649 682 650 683 //Everything is ready to go to sleep 651 park( __cfaabi_dbg_ctx);684 park(); 652 685 653 686 // We are back, restore the owners and recursions … … 691 724 692 725 //Everything is ready to go to sleep 693 park( __cfaabi_dbg_ctx);726 park(); 694 727 695 728 -
libcfa/src/concurrency/monitor.hfa
rae2c27a rc76bd34 53 53 $monitor * m; 54 54 __monitor_group_t prev; 55 bool join; 55 56 }; 56 57 57 void ?{}( monitor_dtor_guard_t & this, $monitor ** m, void (*func)() );58 void ?{}( monitor_dtor_guard_t & this, $monitor ** m, void (*func)(), bool join ); 58 59 void ^?{}( monitor_dtor_guard_t & this ); 59 60 -
libcfa/src/concurrency/mutex.cfa
rae2c27a rc76bd34 42 42 append( blocked_threads, kernelTLS.this_thread ); 43 43 unlock( lock ); 44 park( __cfaabi_dbg_ctx);44 park(); 45 45 } 46 46 else { … … 65 65 this.is_locked = (this.blocked_threads != 0); 66 66 unpark( 67 pop_head( this.blocked_threads ) __cfaabi_dbg_ctx267 pop_head( this.blocked_threads ) 68 68 ); 69 69 unlock( this.lock ); … … 97 97 append( blocked_threads, kernelTLS.this_thread ); 98 98 unlock( lock ); 99 park( __cfaabi_dbg_ctx);99 park(); 100 100 } 101 101 } … … 124 124 owner = thrd; 125 125 recursion_count = (thrd ? 1 : 0); 126 unpark( thrd __cfaabi_dbg_ctx2);126 unpark( thrd ); 127 127 } 128 128 unlock( lock ); … … 142 142 lock( lock __cfaabi_dbg_ctx2 ); 143 143 unpark( 144 pop_head( this.blocked_threads ) __cfaabi_dbg_ctx2144 pop_head( this.blocked_threads ) 145 145 ); 146 146 unlock( lock ); … … 151 151 while(this.blocked_threads) { 152 152 unpark( 153 pop_head( this.blocked_threads ) __cfaabi_dbg_ctx2153 pop_head( this.blocked_threads ) 154 154 ); 155 155 } … … 161 161 append( this.blocked_threads, kernelTLS.this_thread ); 162 162 unlock( this.lock ); 163 park( __cfaabi_dbg_ctx);163 park(); 164 164 } 165 165 … … 170 170 unlock(l); 171 171 unlock(this.lock); 172 park( __cfaabi_dbg_ctx);172 park(); 173 173 lock(l); 174 174 } -
libcfa/src/concurrency/preemption.cfa
rae2c27a rc76bd34 274 274 kernelTLS.this_stats = this->curr_cluster->stats; 275 275 #endif 276 __unpark( id, this __cfaabi_dbg_ctx2);276 __unpark( id, this ); 277 277 } 278 278 … … 411 411 static void * alarm_loop( __attribute__((unused)) void * args ) { 412 412 __processor_id_t id; 413 id.full_proc = false; 413 414 id.id = doregister(&id); 414 415 -
libcfa/src/concurrency/thread.cfa
rae2c27a rc76bd34 39 39 link.prev = 0p; 40 40 link.preferred = -1; 41 #if defined( __CFA_WITH_VERIFY__ ) 42 canary = 0x0D15EA5E0D15EA5E; 43 #endif 41 44 42 45 node.next = 0p; … … 48 51 49 52 void ^?{}($thread& this) with( this ) { 53 #if defined( __CFA_WITH_VERIFY__ ) 54 canary = 0xDEADDEADDEADDEAD; 55 #endif 50 56 unregister(curr_cluster, this); 51 57 ^self_cor{}; -
libcfa/src/concurrency/thread.hfa
rae2c27a rc76bd34 88 88 //---------- 89 89 // Park thread: block until corresponding call to unpark, won't block if unpark is already called 90 void park( __cfaabi_dbg_ctx_param);90 void park( void ); 91 91 92 92 //---------- 93 93 // Unpark a thread, if the thread is already blocked, schedule it 94 94 // if the thread is not yet block, signal that it should rerun immediately 95 void unpark( $thread * this __cfaabi_dbg_ctx_param2);95 void unpark( $thread * this ); 96 96 97 97 forall( dtype T | is_thread(T) ) 98 static inline void unpark( T & this __cfaabi_dbg_ctx_param2 ) { if(!&this) return; unpark( get_thread( this ) __cfaabi_dbg_ctx_fwd2);}98 static inline void unpark( T & this ) { if(!&this) return; unpark( get_thread( this ) );} 99 99 100 100 //---------- … … 106 106 void sleep( Duration duration ); 107 107 108 //---------- 109 // join 110 forall( dtype T | is_thread(T) ) 111 T & join( T & this ); 112 108 113 // Local Variables: // 109 114 // mode: c //
Note: See TracChangeset
for help on using the changeset viewer.