1 /****************************************************************************
2 **
3 **  This file is part of GAP, a system for computational discrete algebra.
4 **
5 **  Copyright of GAP belongs to its developers, whose names are too numerous
6 **  to list here. Please refer to the COPYRIGHT file for details.
7 **
8 **  SPDX-License-Identifier: GPL-2.0-or-later
9 */
10 
11 #ifndef GAP_HPC_GUARD_H
12 #define GAP_HPC_GUARD_H
13 
14 #include "hpc/region.h"
15 #include "hpc/tls.h"
16 
17 #ifndef HPCGAP
18 #error This header is only meant to be used with HPC-GAP
19 #endif
20 
21 #ifdef VERBOSE_GUARDS
22 void WriteGuardError(Bag bag,
23     const char *file, unsigned line, const char *func, const char *expr);
24 void ReadGuardError(Bag bag,
25     const char *file, unsigned line, const char *func, const char *expr);
26 #else
27 void WriteGuardError(Bag bag);
28 void ReadGuardError(Bag bag);
29 #endif
30 
31 #ifdef VERBOSE_GUARDS
32 #define WriteGuard(bag) WriteGuardFull(bag, __FILE__, __LINE__, __FUNCTION__, #bag)
WriteGuardFull(Bag bag,const char * file,unsigned line,const char * func,const char * expr)33 static ALWAYS_INLINE Bag WriteGuardFull(Bag bag,
34   const char *file, unsigned line, const char *func, const char *expr)
35 #else
36 static ALWAYS_INLINE Bag WriteGuard(Bag bag)
37 #endif
38 {
39   Region *region;
40   if (!IS_BAG_REF(bag))
41     return bag;
42   region = REGION(bag);
43   if (region && region->owner != GetTLS() && region->alt_owner != GetTLS())
44     WriteGuardError(bag
45 #ifdef VERBOSE_GUARDS
46     , file, line, func, expr
47 #endif
48     );
49   return bag;
50 }
51 
ImpliedWriteGuard(Bag bag)52 EXPORT_INLINE Bag ImpliedWriteGuard(Bag bag)
53 {
54   return bag;
55 }
56 
CheckWriteAccess(Bag bag)57 EXPORT_INLINE int CheckWriteAccess(Bag bag)
58 {
59   Region *region;
60   if (!IS_BAG_REF(bag))
61     return 1;
62   region = REGION(bag);
63   return !(region && region->owner != GetTLS() && region->alt_owner != GetTLS())
64     || TLS(DisableGuards) >= 2;
65 }
66 
CheckExclusiveWriteAccess(Bag bag)67 EXPORT_INLINE int CheckExclusiveWriteAccess(Bag bag)
68 {
69   Region *region;
70   if (!IS_BAG_REF(bag))
71     return 1;
72   region = REGION(bag);
73   if (!region)
74     return 0;
75   return region->owner == GetTLS() || region->alt_owner == GetTLS()
76     || TLS(DisableGuards) >= 2;
77 }
78 
79 #ifdef VERBOSE_GUARDS
80 #define ReadGuard(bag) ReadGuardFull(bag, __FILE__, __LINE__, __FUNCTION__, #bag)
ReadGuardFull(Bag bag,const char * file,unsigned line,const char * func,const char * expr)81 static ALWAYS_INLINE Bag ReadGuardFull(Bag bag,
82   const char *file, unsigned line, const char *func, const char *expr)
83 #else
84 static ALWAYS_INLINE Bag ReadGuard(Bag bag)
85 #endif
86 {
87   Region *region;
88   if (!IS_BAG_REF(bag))
89     return bag;
90   region = REGION(bag);
91   if (region && region->owner != GetTLS() &&
92       !region->readers[TLS(threadID)] && region->alt_owner != GetTLS())
93     ReadGuardError(bag
94 #ifdef VERBOSE_GUARDS
95     , file, line, func, expr
96 #endif
97     );
98   return bag;
99 }
100 
101 
ImpliedReadGuard(Bag bag)102 static ALWAYS_INLINE Bag ImpliedReadGuard(Bag bag)
103 {
104   return bag;
105 }
106 
107 
CheckReadAccess(Bag bag)108 static ALWAYS_INLINE int CheckReadAccess(Bag bag)
109 {
110   Region *region;
111   if (!IS_BAG_REF(bag))
112     return 1;
113   region = REGION(bag);
114   return !(region && region->owner != GetTLS() &&
115     !region->readers[TLS(threadID)] && region->alt_owner != GetTLS())
116     || TLS(DisableGuards) >= 2;
117 }
118 
119 #endif // GAP_HPC_GUARD_H
120