Fork handler mitigations
[c11tester.git] / action.cc
1 #include <stdio.h>
2 #define __STDC_FORMAT_MACROS
3 #include <inttypes.h>
4 #include <stdlib.h>
5
6 #include "model.h"
7 #include "action.h"
8 #include "clockvector.h"
9 #include "common.h"
10 #include "threads-model.h"
11 #include "nodestack.h"
12 #include "wildcard.h"
13
14 #define ACTION_INITIAL_CLOCK 0
15
16 /** @brief A special value to represent a successful trylock */
17 #define VALUE_TRYSUCCESS 1
18
19 /** @brief A special value to represent a failed trylock */
20 #define VALUE_TRYFAILED 0
21
22 /**
23  * @brief Construct a new ModelAction
24  *
25  * @param type The type of action
26  * @param order The memory order of this action. A "don't care" for non-ATOMIC
27  * actions (e.g., THREAD_* or MODEL_* actions).
28  * @param loc The location that this action acts upon
29  * @param value (optional) A value associated with the action (e.g., the value
30  * read or written). Defaults to a given macro constant, for debugging purposes.
31  * @param thread (optional) The Thread in which this action occurred. If NULL
32  * (default), then a Thread is assigned according to the scheduler.
33  */
34 ModelAction::ModelAction(action_type_t type, memory_order order, void *loc,
35                                                                                                  uint64_t value, Thread *thread) :
36         location(loc),
37         position(NULL),
38         reads_from(NULL),
39         last_fence_release(NULL),
40         node(NULL),
41         cv(NULL),
42         rf_cv(NULL),
43         value(value),
44         type(type),
45         order(order),
46         original_order(order),
47         seq_number(ACTION_INITIAL_CLOCK)
48 {
49         /* References to NULL atomic variables can end up here */
50         ASSERT(loc || type == ATOMIC_FENCE || type == NOOP);
51
52         Thread *t = thread ? thread : thread_current();
53         this->tid = t->get_id();
54 }
55
56
57 /**
58  * @brief Construct a new ModelAction
59  *
60  * @param type The type of action
61  * @param order The memory order of this action. A "don't care" for non-ATOMIC
62  * actions (e.g., THREAD_* or MODEL_* actions).
63  * @param loc The location that this action acts upon
64  * @param value (optional) A value associated with the action (e.g., the value
65  * read or written). Defaults to a given macro constant, for debugging purposes.
66  * @param size (optional) The Thread in which this action occurred. If NULL
67  * (default), then a Thread is assigned according to the scheduler.
68  */
69 ModelAction::ModelAction(action_type_t type, memory_order order, void *loc,
70                                                                                                  uint64_t value, int size) :
71         location(loc),
72         position(NULL),
73         reads_from(NULL),
74         last_fence_release(NULL),
75         node(NULL),
76         cv(NULL),
77         rf_cv(NULL),
78         value(value),
79         type(type),
80         order(order),
81         original_order(order),
82         seq_number(ACTION_INITIAL_CLOCK)
83 {
84         /* References to NULL atomic variables can end up here */
85         ASSERT(loc);
86         this->size = size;
87         Thread *t = thread_current();
88         this->tid = t->get_id();
89 }
90
91
92 /**
93  * @brief Construct a new ModelAction with source line number (requires llvm support)
94  *
95  * @param type The type of action
96  * @param order The memory order of this action. A "don't care" for non-ATOMIC
97  * actions (e.g., THREAD_* or MODEL_* actions).
98  * @param loc The location that this action acts upon
99  * @param value (optional) A value associated with the action (e.g., the value
100  * read or written). Defaults to a given macro constant, for debugging purposes.
101  * @param size (optional) The Thread in which this action occurred. If NULL
102  * (default), then a Thread is assigned according to the scheduler.
103  */
104 ModelAction::ModelAction(action_type_t type, const char * position, memory_order order, void *loc,
105                                                                                                  uint64_t value, int size) :
106         location(loc),
107         position(position),
108         reads_from(NULL),
109         last_fence_release(NULL),
110         node(NULL),
111         cv(NULL),
112         rf_cv(NULL),
113         value(value),
114         type(type),
115         order(order),
116         original_order(order),
117         seq_number(ACTION_INITIAL_CLOCK)
118 {
119         /* References to NULL atomic variables can end up here */
120         ASSERT(loc);
121         this->size = size;
122         Thread *t = thread_current();
123         this->tid = t->get_id();
124 }
125
126
127 /**
128  * @brief Construct a new ModelAction with source line number (requires llvm support)
129  *
130  * @param type The type of action
131  * @param position The source line number of this atomic operation
132  * @param order The memory order of this action. A "don't care" for non-ATOMIC
133  * actions (e.g., THREAD_* or MODEL_* actions).
134  * @param loc The location that this action acts upon
135  * @param value (optional) A value associated with the action (e.g., the value
136  * read or written). Defaults to a given macro constant, for debugging purposes.
137  * @param thread (optional) The Thread in which this action occurred. If NULL
138  * (default), then a Thread is assigned according to the scheduler.
139  */
140 ModelAction::ModelAction(action_type_t type, const char * position, memory_order order,
141                                                                                                  void *loc, uint64_t value, Thread *thread) :
142         location(loc),
143         position(position),
144         reads_from(NULL),
145         last_fence_release(NULL),
146         node(NULL),
147         cv(NULL),
148         rf_cv(NULL),
149         value(value),
150         type(type),
151         order(order),
152         original_order(order),
153         seq_number(ACTION_INITIAL_CLOCK)
154 {
155         /* References to NULL atomic variables can end up here */
156         ASSERT(loc || type == ATOMIC_FENCE);
157
158         Thread *t = thread ? thread : thread_current();
159         this->tid = t->get_id();
160         // model_print("position: %s\n", position);
161 }
162
163
164 /** @brief ModelAction destructor */
165 ModelAction::~ModelAction()
166 {
167         /**
168          * We can't free the clock vector:
169          * Clock vectors are snapshotting state. When we delete model actions,
170          * they are at the end of the node list and have invalid old clock
171          * vectors which have already been rolled back to an unallocated state.
172          */
173
174         /*
175            if (cv)
176                 delete cv; */
177 }
178
179 int ModelAction::getSize() const {
180         return size;
181 }
182
183 void ModelAction::copy_from_new(ModelAction *newaction)
184 {
185         seq_number = newaction->seq_number;
186 }
187
188 void ModelAction::set_seq_number(modelclock_t num)
189 {
190         /* ATOMIC_UNINIT actions should never have non-zero clock */
191         ASSERT(!is_uninitialized());
192         ASSERT(seq_number == ACTION_INITIAL_CLOCK);
193         seq_number = num;
194 }
195
196 bool ModelAction::is_thread_start() const
197 {
198         return type == THREAD_START;
199 }
200
201 bool ModelAction::is_thread_join() const
202 {
203         return type == THREAD_JOIN || type == PTHREAD_JOIN;
204 }
205
206 bool ModelAction::is_mutex_op() const
207 {
208         return type == ATOMIC_LOCK || type == ATOMIC_TRYLOCK || type == ATOMIC_UNLOCK || type == ATOMIC_WAIT || type == ATOMIC_NOTIFY_ONE || type == ATOMIC_NOTIFY_ALL;
209 }
210
211 bool ModelAction::is_lock() const
212 {
213         return type == ATOMIC_LOCK;
214 }
215
216 bool ModelAction::is_wait() const {
217         return type == ATOMIC_WAIT;
218 }
219
220 bool ModelAction::is_notify() const {
221         return type == ATOMIC_NOTIFY_ONE || type == ATOMIC_NOTIFY_ALL;
222 }
223
224 bool ModelAction::is_notify_one() const {
225         return type == ATOMIC_NOTIFY_ONE;
226 }
227
228 bool ModelAction::is_unlock() const
229 {
230         return type == ATOMIC_UNLOCK;
231 }
232
233 bool ModelAction::is_trylock() const
234 {
235         return type == ATOMIC_TRYLOCK;
236 }
237
238 bool ModelAction::is_success_lock() const
239 {
240         return type == ATOMIC_LOCK || (type == ATOMIC_TRYLOCK && value == VALUE_TRYSUCCESS);
241 }
242
243 bool ModelAction::is_failed_trylock() const
244 {
245         return (type == ATOMIC_TRYLOCK && value == VALUE_TRYFAILED);
246 }
247
248 /** @return True if this operation is performed on a C/C++ atomic variable */
249 bool ModelAction::is_atomic_var() const
250 {
251         return is_read() || could_be_write();
252 }
253
254 bool ModelAction::is_uninitialized() const
255 {
256         return type == ATOMIC_UNINIT;
257 }
258
259 bool ModelAction::is_read() const
260 {
261         return type == ATOMIC_READ || type == ATOMIC_RMWR || type == ATOMIC_RMWRCAS || type == ATOMIC_RMW;
262 }
263
264 bool ModelAction::is_write() const
265 {
266         return type == ATOMIC_WRITE || type == ATOMIC_RMW || type == ATOMIC_INIT || type == ATOMIC_UNINIT;
267 }
268
269 bool ModelAction::could_be_write() const
270 {
271         return is_write() || is_rmwr();
272 }
273
274 bool ModelAction::is_yield() const
275 {
276         return type == THREAD_YIELD;
277 }
278
279 bool ModelAction::is_rmwr() const
280 {
281         return type == ATOMIC_RMWR || type == ATOMIC_RMWRCAS;
282 }
283
284 bool ModelAction::is_rmwrcas() const
285 {
286         return type == ATOMIC_RMWRCAS;
287 }
288
289 bool ModelAction::is_rmw() const
290 {
291         return type == ATOMIC_RMW;
292 }
293
294 bool ModelAction::is_rmwc() const
295 {
296         return type == ATOMIC_RMWC;
297 }
298
299 bool ModelAction::is_fence() const
300 {
301         return type == ATOMIC_FENCE;
302 }
303
304 bool ModelAction::is_initialization() const
305 {
306         return type == ATOMIC_INIT;
307 }
308
309 bool ModelAction::is_annotation() const
310 {
311         return type == ATOMIC_ANNOTATION;
312 }
313
314 bool ModelAction::is_relaxed() const
315 {
316         return order == std::memory_order_relaxed;
317 }
318
319 bool ModelAction::is_acquire() const
320 {
321         switch (order) {
322         case std::memory_order_acquire:
323         case std::memory_order_acq_rel:
324         case std::memory_order_seq_cst:
325                 return true;
326         default:
327                 return false;
328         }
329 }
330
331 bool ModelAction::is_release() const
332 {
333         switch (order) {
334         case std::memory_order_release:
335         case std::memory_order_acq_rel:
336         case std::memory_order_seq_cst:
337                 return true;
338         default:
339                 return false;
340         }
341 }
342
343 bool ModelAction::is_seqcst() const
344 {
345         return order == std::memory_order_seq_cst;
346 }
347
348 bool ModelAction::same_var(const ModelAction *act) const
349 {
350         if (act->is_wait() || is_wait()) {
351                 if (act->is_wait() && is_wait()) {
352                         if (((void *)value) == ((void *)act->value))
353                                 return true;
354                 } else if (is_wait()) {
355                         if (((void *)value) == act->location)
356                                 return true;
357                 } else if (act->is_wait()) {
358                         if (location == ((void *)act->value))
359                                 return true;
360                 }
361         }
362
363         return location == act->location;
364 }
365
366 bool ModelAction::same_thread(const ModelAction *act) const
367 {
368         return tid == act->tid;
369 }
370
371 void ModelAction::copy_typeandorder(ModelAction * act)
372 {
373         this->type = act->type;
374         this->order = act->order;
375 }
376
377 /**
378  * Get the Thread which is the operand of this action. This is only valid for
379  * THREAD_* operations (currently only for THREAD_CREATE and THREAD_JOIN). Note
380  * that this provides a central place for determining the conventions of Thread
381  * storage in ModelAction, where we generally aren't very type-safe (e.g., we
382  * store object references in a (void *) address.
383  *
384  * For THREAD_CREATE, this yields the Thread which is created.
385  * For THREAD_JOIN, this yields the Thread we are joining with.
386  *
387  * @return The Thread which this action acts on, if exists; otherwise NULL
388  */
389 Thread * ModelAction::get_thread_operand() const
390 {
391         if (type == THREAD_CREATE) {
392                 /* thread_operand is set in execution.cc */
393                 return thread_operand;
394         } else if (type == PTHREAD_CREATE) {
395                 return thread_operand;
396         } else if (type == THREAD_JOIN) {
397                 /* THREAD_JOIN uses (Thread *) for location */
398                 return (Thread *)get_location();
399         } else if (type == PTHREAD_JOIN) {
400                 // return NULL;
401                 // thread_operand is stored in execution::pthread_map;
402                 return (Thread *)get_location();
403         } else
404                 return NULL;
405 }
406
407 /**
408  * @brief Convert the read portion of an RMW
409  *
410  * Changes an existing read part of an RMW action into either:
411  *  -# a full RMW action in case of the completed write or
412  *  -# a READ action in case a failed action.
413  *
414  * @todo  If the memory_order changes, we may potentially need to update our
415  * clock vector.
416  *
417  * @param act The second half of the RMW (either RMWC or RMW)
418  */
419 void ModelAction::process_rmw(ModelAction *act)
420 {
421         this->order = act->order;
422         if (act->is_rmwc())
423                 this->type = ATOMIC_READ;
424         else if (act->is_rmw()) {
425                 this->type = ATOMIC_RMW;
426                 this->value = act->value;
427         }
428 }
429
430 /**
431  * @brief Check if this action should be backtracked with another, due to
432  * potential synchronization
433  *
434  * The is_synchronizing method should only explore interleavings if:
435  *  -# the operations are seq_cst and don't commute or
436  *  -# the reordering may establish or break a synchronization relation.
437  *
438  * Other memory operations will be dealt with by using the reads_from relation.
439  *
440  * @param act The action to consider exploring a reordering
441  * @return True, if we have to explore a reordering; otherwise false
442  */
443 bool ModelAction::could_synchronize_with(const ModelAction *act) const
444 {
445         // Same thread can't be reordered
446         if (same_thread(act))
447                 return false;
448
449         // Different locations commute
450         if (!same_var(act) && !is_fence() && !act->is_fence())
451                 return false;
452
453         // Explore interleavings of seqcst writes/fences to guarantee total
454         // order of seq_cst operations that don't commute
455         if ((could_be_write() || act->could_be_write() || is_fence() || act->is_fence()) && is_seqcst() && act->is_seqcst())
456                 return true;
457
458         // Explore synchronizing read/write pairs
459         if (is_acquire() && act->is_release() && is_read() && act->could_be_write())
460                 return true;
461
462         // lock just released...we can grab lock
463         if ((is_lock() || is_trylock()) && (act->is_unlock() || act->is_wait()))
464                 return true;
465
466         // lock just acquired...we can fail to grab lock
467         if (is_trylock() && act->is_success_lock())
468                 return true;
469
470         // other thread stalling on lock...we can release lock
471         if (is_unlock() && (act->is_trylock() || act->is_lock()))
472                 return true;
473
474         if (is_trylock() && (act->is_unlock() || act->is_wait()))
475                 return true;
476
477         if (is_notify() && act->is_wait())
478                 return true;
479
480         if (is_wait() && act->is_notify())
481                 return true;
482
483         // Otherwise handle by reads_from relation
484         return false;
485 }
486
487 bool ModelAction::is_conflicting_lock(const ModelAction *act) const
488 {
489         // Must be different threads to reorder
490         if (same_thread(act))
491                 return false;
492
493         // Try to reorder a lock past a successful lock
494         if (act->is_success_lock())
495                 return true;
496
497         // Try to push a successful trylock past an unlock
498         if (act->is_unlock() && is_trylock() && value == VALUE_TRYSUCCESS)
499                 return true;
500
501         // Try to push a successful trylock past a wait
502         if (act->is_wait() && is_trylock() && value == VALUE_TRYSUCCESS)
503                 return true;
504
505         return false;
506 }
507
508 /**
509  * Create a new clock vector for this action. Note that this function allows a
510  * user to clobber (and leak) a ModelAction's existing clock vector. A user
511  * should ensure that the vector has already either been rolled back
512  * (effectively "freed") or freed.
513  *
514  * @param parent A ModelAction from which to inherit a ClockVector
515  */
516 void ModelAction::create_cv(const ModelAction *parent)
517 {
518         if (parent)
519                 cv = new ClockVector(parent->cv, this);
520         else
521                 cv = new ClockVector(NULL, this);
522 }
523
524 void ModelAction::set_try_lock(bool obtainedlock)
525 {
526         value = obtainedlock ? VALUE_TRYSUCCESS : VALUE_TRYFAILED;
527 }
528
529 /**
530  * @brief Get the value read by this load
531  *
532  * We differentiate this function from ModelAction::get_write_value and
533  * ModelAction::get_value for the purpose of RMW's, which may have both a
534  * 'read' and a 'write' value.
535  *
536  * Note: 'this' must be a load.
537  *
538  * @return The value read by this load
539  */
540 uint64_t ModelAction::get_reads_from_value() const
541 {
542         ASSERT(is_read());
543         if (reads_from)
544                 return reads_from->get_write_value();
545
546         return VALUE_NONE;      // Only for new actions with no reads-from
547 }
548
549 /**
550  * @brief Get the value written by this store
551  *
552  * We differentiate this function from ModelAction::get_reads_from_value and
553  * ModelAction::get_value for the purpose of RMW's, which may have both a
554  * 'read' and a 'write' value.
555  *
556  * Note: 'this' must be a store.
557  *
558  * @return The value written by this store
559  */
560 uint64_t ModelAction::get_write_value() const
561 {
562         ASSERT(is_write());
563         return value;
564 }
565
566 /**
567  * @brief Get the value returned by this action
568  *
569  * For atomic reads (including RMW), an operation returns the value it read.
570  * For atomic writes, an operation returns the value it wrote. For other
571  * operations, the return value varies (sometimes is a "don't care"), but the
572  * value is simply stored in the "value" field.
573  *
574  * @return This action's return value
575  */
576 uint64_t ModelAction::get_return_value() const
577 {
578         if (is_read())
579                 return get_reads_from_value();
580         else if (is_write())
581                 return get_write_value();
582         else
583                 return value;
584 }
585
586 /** @return The Node associated with this ModelAction */
587 Node * ModelAction::get_node() const
588 {
589         /* UNINIT actions do not have a Node */
590         ASSERT(!is_uninitialized());
591         return node;
592 }
593
594 /**
595  * Update the model action's read_from action
596  * @param act The action to read from; should be a write
597  */
598 void ModelAction::set_read_from(ModelAction *act)
599 {
600         ASSERT(act);
601
602         reads_from = act;
603
604         if (act->is_uninitialized()) {  // WL
605                 uint64_t val = *((uint64_t *) location);
606                 ModelAction * act_initialized = (ModelAction *)act;
607                 act_initialized->set_value(val);
608                 reads_from = act_initialized;
609
610 // disabled by WL, because LLVM IR is unable to detect atomic init
611 /*              model->assert_bug("May read from uninitialized atomic:\n"
612                                 "    action %d, thread %d, location %p (%s, %s)",
613                                 seq_number, id_to_int(tid), location,
614                                 get_type_str(), get_mo_str());
615  */
616         }
617 }
618
619 /**
620  * Synchronize the current thread with the thread corresponding to the
621  * ModelAction parameter.
622  * @param act The ModelAction to synchronize with
623  * @return True if this is a valid synchronization; false otherwise
624  */
625 bool ModelAction::synchronize_with(const ModelAction *act)
626 {
627         if (*this < *act)
628                 return false;
629         cv->merge(act->cv);
630         return true;
631 }
632
633 bool ModelAction::has_synchronized_with(const ModelAction *act) const
634 {
635         return cv->synchronized_since(act);
636 }
637
638 /**
639  * Check whether 'this' happens before act, according to the memory-model's
640  * happens before relation. This is checked via the ClockVector constructs.
641  * @return true if this action's thread has synchronized with act's thread
642  * since the execution of act, false otherwise.
643  */
644 bool ModelAction::happens_before(const ModelAction *act) const
645 {
646         return act->cv->synchronized_since(this);
647 }
648
649 const char * ModelAction::get_type_str() const
650 {
651         switch (this->type) {
652         case THREAD_CREATE: return "thread create";
653         case THREAD_START: return "thread start";
654         case THREAD_YIELD: return "thread yield";
655         case THREAD_JOIN: return "thread join";
656         case THREAD_FINISH: return "thread finish";
657
658         case PTHREAD_CREATE: return "pthread create";
659         case PTHREAD_JOIN: return "pthread join";
660
661         case ATOMIC_UNINIT: return "uninitialized";
662         case ATOMIC_READ: return "atomic read";
663         case ATOMIC_WRITE: return "atomic write";
664         case ATOMIC_RMW: return "atomic rmw";
665         case ATOMIC_FENCE: return "fence";
666         case ATOMIC_RMWR: return "atomic rmwr";
667         case ATOMIC_RMWRCAS: return "atomic rmwrcas";
668         case ATOMIC_RMWC: return "atomic rmwc";
669         case ATOMIC_INIT: return "init atomic";
670         case ATOMIC_LOCK: return "lock";
671         case ATOMIC_UNLOCK: return "unlock";
672         case ATOMIC_TRYLOCK: return "trylock";
673         case ATOMIC_WAIT: return "wait";
674         case ATOMIC_NOTIFY_ONE: return "notify one";
675         case ATOMIC_NOTIFY_ALL: return "notify all";
676         case ATOMIC_ANNOTATION: return "annotation";
677         default: return "unknown type";
678         };
679 }
680
681 const char * ModelAction::get_mo_str() const
682 {
683         switch (this->order) {
684         case std::memory_order_relaxed: return "relaxed";
685         case std::memory_order_acquire: return "acquire";
686         case std::memory_order_release: return "release";
687         case std::memory_order_acq_rel: return "acq_rel";
688         case std::memory_order_seq_cst: return "seq_cst";
689         default: return "unknown";
690         }
691 }
692
693 /** @brief Print nicely-formatted info about this ModelAction */
694 void ModelAction::print() const
695 {
696         const char *type_str = get_type_str(), *mo_str = get_mo_str();
697
698         model_print("%-4d %-2d   %-14s  %7s  %14p   %-#18" PRIx64,
699                                                         seq_number, id_to_int(tid), type_str, mo_str, location, get_return_value());
700         if (is_read()) {
701                 if (reads_from)
702                         model_print("  %-3d", reads_from->get_seq_number());
703                 else
704                         model_print("  ?  ");
705         }
706         if (cv) {
707                 if (is_read())
708                         model_print(" ");
709                 else
710                         model_print("      ");
711                 cv->print();
712         } else
713                 model_print("\n");
714 }
715
716 /** @brief Get a (likely) unique hash for this ModelAction */
717 unsigned int ModelAction::hash() const
718 {
719         unsigned int hash = (unsigned int)this->type;
720         hash ^= ((unsigned int)this->order) << 3;
721         hash ^= seq_number << 5;
722         hash ^= id_to_int(tid) << 6;
723
724         if (is_read()) {
725                 if (reads_from)
726                         hash ^= reads_from->get_seq_number();
727                 hash ^= get_reads_from_value();
728         }
729         return hash;
730 }
731
732 /**
733  * Only valid for LOCK, TRY_LOCK, UNLOCK, and WAIT operations.
734  * @return The mutex operated on by this action, if any; otherwise NULL
735  */
736 cdsc::mutex * ModelAction::get_mutex() const
737 {
738         if (is_trylock() || is_lock() || is_unlock())
739                 return (cdsc::mutex *)get_location();
740         else if (is_wait())
741                 return (cdsc::mutex *)get_value();
742         else
743                 return NULL;
744 }