@@ -16,7 +16,6 @@ use ptr;
16
16
use option:: * ;
17
17
use either:: { Either , Left , Right } ;
18
18
use task;
19
- use task:: atomically;
20
19
use unstable:: atomics:: { AtomicOption , AtomicUint , Acquire , Release , SeqCst } ;
21
20
use unstable:: finally:: Finally ;
22
21
use ops:: Drop ;
@@ -271,6 +270,48 @@ impl<T> Drop for UnsafeAtomicRcBox<T>{
271
270
272
271
/****************************************************************************/
273
272
273
+ /**
274
+ * Enables a runtime assertion that no operation in the argument closure shall
275
+ * use scheduler operations (yield, recv, spawn, etc). This is for use with
276
+ * pthread mutexes, which may block the entire scheduler thread, rather than
277
+ * just one task, and is hence prone to deadlocks if mixed with yielding.
278
+ *
279
+ * NOTE: THIS DOES NOT PROVIDE LOCKING, or any sort of critical-section
280
+ * synchronization whatsoever. It only makes sense to use for CPU-local issues.
281
+ */
282
+ // FIXME(#8140) should not be pub
283
+ pub unsafe fn atomically < U > ( f : & fn ( ) -> U ) -> U {
284
+ use rt:: task:: Task ;
285
+ use task:: rt;
286
+ use rt:: local:: Local ;
287
+ use rt:: { context, OldTaskContext , TaskContext } ;
288
+
289
+ match context ( ) {
290
+ OldTaskContext => {
291
+ let t = rt:: rust_get_task ( ) ;
292
+ do ( || {
293
+ rt:: rust_task_inhibit_kill ( t) ;
294
+ rt:: rust_task_inhibit_yield ( t) ;
295
+ f ( )
296
+ } ) . finally {
297
+ rt:: rust_task_allow_yield ( t) ;
298
+ rt:: rust_task_allow_kill ( t) ;
299
+ }
300
+ }
301
+ TaskContext => {
302
+ let t = Local :: unsafe_borrow :: < Task > ( ) ;
303
+ do ( || {
304
+ ( * t) . death . inhibit_yield ( ) ;
305
+ f ( )
306
+ } ) . finally {
307
+ ( * t) . death . allow_yield ( ) ;
308
+ }
309
+ }
310
+ // FIXME(#3095): As in unkillable().
311
+ _ => f ( )
312
+ }
313
+ }
314
+
274
315
#[ allow( non_camel_case_types) ] // runtime type
275
316
type rust_little_lock = * libc:: c_void ;
276
317
@@ -395,11 +436,18 @@ mod tests {
395
436
use cell:: Cell ;
396
437
use comm;
397
438
use option:: * ;
398
- use super :: { Exclusive , UnsafeAtomicRcBox } ;
439
+ use super :: { Exclusive , UnsafeAtomicRcBox , atomically } ;
399
440
use task;
400
441
use uint;
401
442
use util;
402
443
444
+ #[ test]
445
+ fn test_atomically ( ) {
446
+ // NB. The whole runtime will abort on an 'atomic-sleep' violation,
447
+ // so we can't really test for the converse behaviour.
448
+ unsafe { do atomically { } } task:: yield ( ) ; // oughtn't fail
449
+ }
450
+
403
451
#[ test]
404
452
fn exclusive_new_arc ( ) {
405
453
unsafe {
0 commit comments