1 // SPDX-License-Identifier: GPL-2.0-or-later 2 /* 3 * Copyright (c) 2020 Linaro Limited. All rights reserved. 4 * Author: Viresh Kumar <viresh.kumar@linaro.org> 5 */ 6 7 #ifndef LAPI_SEMBUF_H__ 8 #define LAPI_SEMBUF_H__ 9 10 #include "lapi/posix_types.h" 11 #include <sys/sem.h> 12 #include "tst_timer.h" 13 #include "ipcbuf.h" 14 15 #ifndef HAVE_STRUCT_SEMID64_DS 16 17 #if defined(__mips__) 18 #define HAVE_SEMID64_DS 19 /* 20 * The semid64_ds structure for the MIPS architecture. 21 * Note extra padding because this structure is passed back and forth 22 * between kernel and user space. 23 * 24 * Pad space is left for 2 miscellaneous 64-bit values on mips64, 25 * but used for the upper 32 bit of the time values on mips32. 26 */ 27 #if __BITS_PER_LONG == 64 28 struct semid64_ds { 29 struct ipc64_perm sem_perm; /* permissions .. see ipc.h */ 30 long sem_otime; /* last semop time */ 31 long sem_ctime; /* last change time */ 32 unsigned long sem_nsems; /* no. of semaphores in array */ 33 unsigned long __unused1; 34 unsigned long __unused2; 35 }; 36 #else 37 #define HAVE_SEMID64_DS_TIME_HIGH 38 struct semid64_ds { 39 struct ipc64_perm sem_perm; /* permissions .. see ipc.h */ 40 unsigned long sem_otime; /* last semop time */ 41 unsigned long sem_ctime; /* last change time */ 42 unsigned long sem_nsems; /* no. of semaphores in array */ 43 unsigned long sem_otime_high; 44 unsigned long sem_ctime_high; 45 }; 46 #endif 47 #endif /* __mips__ */ 48 49 #if defined(__hppa__) 50 #define HAVE_SEMID64_DS 51 /* 52 * The semid64_ds structure for parisc architecture. 53 * Note extra padding because this structure is passed back and forth 54 * between kernel and user space. 55 * 56 * Pad space is left for: 57 * - 2 miscellaneous 32-bit values 58 */ 59 struct semid64_ds { 60 struct ipc64_perm sem_perm; /* permissions .. see ipc.h */ 61 #if __BITS_PER_LONG == 64 62 long sem_otime; /* last semop time */ 63 long sem_ctime; /* last change time */ 64 #else 65 #define HAVE_SEMID64_DS_TIME_HIGH 66 unsigned long sem_otime_high; 67 unsigned long sem_otime; /* last semop time */ 68 unsigned long sem_ctime_high; 69 unsigned long sem_ctime; /* last change time */ 70 #endif 71 unsigned long sem_nsems; /* no. of semaphores in array */ 72 unsigned long __unused1; 73 unsigned long __unused2; 74 }; 75 #endif /* __hppa__ */ 76 77 #if defined(__powerpc__) || defined(__powerpc64__) 78 #define HAVE_SEMID64_DS 79 /* 80 * The semid64_ds structure for PPC architecture. 81 * Note extra padding because this structure is passed back and forth 82 * between kernel and user space. 83 * 84 * Pad space is left for: 85 * - 2 miscellaneous 32/64-bit values 86 */ 87 88 struct semid64_ds { 89 struct ipc64_perm sem_perm; /* permissions .. see ipc.h */ 90 #ifndef __powerpc64__ 91 #define HAVE_SEMID64_DS_TIME_HIGH 92 unsigned long sem_otime_high; 93 unsigned long sem_otime; /* last semop time */ 94 unsigned long sem_ctime_high; 95 unsigned long sem_ctime; /* last change time */ 96 #else 97 long sem_otime; /* last semop time */ 98 long sem_ctime; /* last change time */ 99 #endif 100 unsigned long sem_nsems; /* no. of semaphores in array */ 101 unsigned long __unused3; 102 unsigned long __unused4; 103 }; 104 #endif /* defined(__powerpc__) || defined(__powerpc64__) */ 105 106 #if defined(__sparc__) 107 #define HAVE_SEMID64_DS 108 /* 109 * The semid64_ds structure for sparc architecture. 110 * Note extra padding because this structure is passed back and forth 111 * between kernel and user space. 112 * 113 * Pad space is left for: 114 * - 2 miscellaneous 32-bit values 115 */ 116 117 struct semid64_ds { 118 struct ipc64_perm sem_perm; /* permissions .. see ipc.h */ 119 #if defined(__arch64__) 120 long sem_otime; /* last semop time */ 121 long sem_ctime; /* last change time */ 122 #else 123 #define HAVE_SEMID64_DS_TIME_HIGH 124 unsigned long sem_otime_high; 125 unsigned long sem_otime; /* last semop time */ 126 unsigned long sem_ctime_high; 127 unsigned long sem_ctime; /* last change time */ 128 #endif 129 unsigned long sem_nsems; /* no. of semaphores in array */ 130 unsigned long __unused1; 131 unsigned long __unused2; 132 }; 133 #endif /* __sparc__ */ 134 135 #if defined(__x86_64__) 136 #define HAVE_SEMID64_DS 137 /* 138 * The semid64_ds structure for x86 architecture. 139 * Note extra padding because this structure is passed back and forth 140 * between kernel and user space. 141 * 142 * Pad space is left for: 143 * - 2 miscellaneous 32-bit values 144 * 145 * x86_64 and x32 incorrectly added padding here, so the structures 146 * are still incompatible with the padding on x86. 147 */ 148 struct semid64_ds { 149 struct ipc64_perm sem_perm; /* permissions .. see ipc.h */ 150 #ifdef __i386__ 151 #define HAVE_SEMID64_DS_TIME_HIGH 152 unsigned long sem_otime; /* last semop time */ 153 unsigned long sem_otime_high; 154 unsigned long sem_ctime; /* last change time */ 155 unsigned long sem_ctime_high; 156 #else 157 __kernel_long_t sem_otime; /* last semop time */ 158 __kernel_ulong_t __unused1; 159 __kernel_long_t sem_ctime; /* last change time */ 160 __kernel_ulong_t __unused2; 161 #endif 162 __kernel_ulong_t sem_nsems; /* no. of semaphores in array */ 163 __kernel_ulong_t __unused3; 164 __kernel_ulong_t __unused4; 165 }; 166 #endif /* defined(__x86_64__) */ 167 168 #if defined(__xtensa__) 169 #define HAVE_SEMID64_DS 170 #define HAVE_SEMID64_DS_TIME_HIGH 171 172 struct semid64_ds { 173 struct ipc64_perm sem_perm; /* permissions .. see ipc.h */ 174 #ifdef __XTENSA_EL__ 175 unsigned long sem_otime; /* last semop time */ 176 unsigned long sem_otime_high; 177 unsigned long sem_ctime; /* last change time */ 178 unsigned long sem_ctime_high; 179 #else 180 unsigned long sem_otime_high; 181 unsigned long sem_otime; /* last semop time */ 182 unsigned long sem_ctime_high; 183 unsigned long sem_ctime; /* last change time */ 184 #endif 185 unsigned long sem_nsems; /* no. of semaphores in array */ 186 unsigned long __unused3; 187 unsigned long __unused4; 188 }; 189 190 #endif /* __xtensa__ */ 191 192 #ifndef HAVE_SEMID64_DS 193 /* 194 * The semid64_ds structure for most architectures (though it came 195 * from x86_32 originally). Note extra padding because this structure 196 * is passed back and forth between kernel and user space. 197 * 198 * semid64_ds was originally meant to be architecture specific, but 199 * everyone just ended up making identical copies without specific 200 * optimizations, so we may just as well all use the same one. 201 * 202 * 64 bit architectures use a 64-bit long time field here, while 203 * 32 bit architectures have a pair of unsigned long values. 204 * 205 * On big-endian systems, the padding is in the wrong place for 206 * historic reasons, so user space has to reconstruct a time_t 207 * value using 208 * 209 * user_semid_ds.sem_otime = kernel_semid64_ds.sem_otime + 210 * ((long long)kernel_semid64_ds.sem_otime_high << 32) 211 * 212 * Pad space is left for 2 miscellaneous 32-bit values 213 */ 214 struct semid64_ds { 215 struct ipc64_perm sem_perm; /* permissions .. see ipc.h */ 216 #if __BITS_PER_LONG == 64 217 long sem_otime; /* last semop time */ 218 long sem_ctime; /* last change time */ 219 #else 220 #define HAVE_SEMID64_DS_TIME_HIGH 221 unsigned long sem_otime; /* last semop time */ 222 unsigned long sem_otime_high; 223 unsigned long sem_ctime; /* last change time */ 224 unsigned long sem_ctime_high; 225 #endif 226 unsigned long sem_nsems; /* no. of semaphores in array */ 227 unsigned long __unused3; 228 unsigned long __unused4; 229 }; 230 #endif /* semid64_ds */ 231 232 #endif /* HAVE_SEMID64_DS */ 233 234 #endif /* LAPI_SEMBUF_H__ */ 235