]>
git.saurik.com Git - apple/xnu.git/blob - tests/testposixshm.c
6 #include <sys/sysctl.h>
8 #include <TargetConditionals.h>
10 #include <darwintest.h>
12 T_GLOBAL_META(T_META_RUN_CONCURRENTLY(true));
14 static int nthreads
= 0;
16 static _Atomic
int phase
= 0;
17 static _Atomic
int pass_count
= 0;
18 static _Atomic
int fail_count
= 0;
21 worker_thread_func(__unused
void *arg
)
26 /* test racing shm_open */
27 while (atomic_load(&phase
) == 0) {
30 myfd
= shm_open("abcd", O_RDWR
| O_CREAT
| O_EXCL
, S_IRUSR
| S_IWUSR
);
32 T_QUIET
; T_EXPECT_EQ(errno
, EEXIST
, "Expected EEXIST");
33 atomic_fetch_add(&fail_count
, 1);
36 atomic_fetch_add(&pass_count
, 1);
39 /* test racing ftruncate */
40 while (atomic_load(&phase
) == 1) {
43 error
= ftruncate(fd
, 8 * 1024);
45 T_QUIET
; T_EXPECT_EQ(errno
, EINVAL
, "Expected EINVAL");
46 atomic_fetch_add(&fail_count
, 1);
48 atomic_fetch_add(&pass_count
, 1);
51 /* test racing close */
52 while (atomic_load(&phase
) == 2) {
57 T_QUIET
; T_EXPECT_EQ(errno
, EBADF
, "Expected EBADF");
58 atomic_fetch_add(&fail_count
, 1);
60 atomic_fetch_add(&pass_count
, 1);
63 /* test racing shm_unlink() */
64 while (atomic_load(&phase
) == 3) {
67 error
= shm_unlink("abcd");
69 T_QUIET
; T_EXPECT_EQ(errno
, ENOENT
, "Expected ENOENT");
70 atomic_fetch_add(&fail_count
, 1);
72 atomic_fetch_add(&pass_count
, 1);
82 size_t ncpu_size
= sizeof(ncpu
);
86 ret
= sysctlbyname("hw.ncpu", &ncpu
, &ncpu_size
, NULL
, 0);
87 T_ASSERT_POSIX_SUCCESS(ret
, "sysctlbyname(hw.ncpu)");
89 T_QUIET
; T_LOG("%s: Detected %d CPUs\n", __FUNCTION__
, ncpu
);
92 T_QUIET
; T_LOG("%s: Will create %d threads\n", __FUNCTION__
, nthreads
);
94 ret
= pthread_attr_init(&attr
);
95 T_QUIET
; T_ASSERT_MACH_SUCCESS(ret
, "pthread_attr_init");
97 for (i
= 0; i
< nthreads
; i
++) {
99 ret
= pthread_create(&thread
, &attr
, worker_thread_func
, NULL
);
100 T_QUIET
; T_ASSERT_POSIX_ZERO(ret
, "pthread_create");
105 T_DECL(testposixshm
, "Posix Shared Memory tests")
111 char *toolong
= "12345678901234567890123456789012";
112 char *maxname
= "1234567890123456789012345678901";
114 /* must have O_CREAT */
115 fd1
= shm_open(maxname
, O_RDWR
, S_IRUSR
| S_IWUSR
);
116 T_EXPECT_EQ(fd1
, -1, "shm_open() missing O_CREAT");
118 T_EXPECT_EQ(errno
, ENOENT
, "Expected ENOENT");
121 fd1
= shm_open(toolong
, O_RDWR
| O_CREAT
, S_IRUSR
| S_IWUSR
);
122 T_EXPECT_EQ(fd1
, -1, "shm_open() name too long");
124 T_EXPECT_EQ(errno
, ENAMETOOLONG
, "Expected ENAMETOOLONG");
127 fd1
= shm_open(noname
, O_RDWR
| O_CREAT
, S_IRUSR
| S_IWUSR
);
128 T_EXPECT_EQ(fd1
, -1, "shm_open() invalid name");
130 T_EXPECT_EQ(errno
, EINVAL
, "Expected EINVAL");
133 fd1
= shm_open(maxname
, O_RDWR
| O_CREAT
, S_IRUSR
| S_IWUSR
);
134 T_EXPECT_POSIX_SUCCESS(fd1
, "valid shm_open() result");
136 /* O_CREAT, but not O_EXCL should work */
137 fd2
= shm_open(maxname
, O_RDWR
| O_CREAT
, S_IRUSR
| S_IWUSR
);
138 T_EXPECT_POSIX_SUCCESS(fd2
, "shm_open() no O_EXCL");
140 /* close should work */
141 T_EXPECT_POSIX_ZERO(close(fd2
), "close()");
143 /* O_CREAT | O_EXCL should fail */
144 fd2
= shm_open(maxname
, O_RDWR
| O_CREAT
| O_EXCL
, S_IRUSR
| S_IWUSR
);
146 T_EXPECT_EQ(fd2
, -1, "shm_open() existing but O_EXCL");
147 T_EXPECT_EQ(errno
, EEXIST
, "Expected EEXIST");
149 /* use ftruncate to create the memory */
150 T_EXPECT_POSIX_ZERO(ftruncate(fd1
, 16 * 1024), NULL
);
152 /* a second ftruncate should fail */
154 T_EXPECT_EQ(ftruncate(fd1
, 8 * 1024), -1, "second ftruncate() should fail");
155 T_EXPECT_EQ(errno
, EINVAL
, "Expected EINVAL");
157 /* Map the memory object */
158 addr
= mmap(0, 4 * 1024, PROT_READ
| PROT_WRITE
, MAP_SHARED
, fd1
, 0);
160 T_EXPECT_NE((void *)addr
, MAP_FAILED
, "mmap() should work");
162 /* close should work */
163 T_EXPECT_POSIX_ZERO(close(fd1
), "close()");
165 /* unlink should work */
166 T_EXPECT_POSIX_SUCCESS(shm_unlink(maxname
), "shm_unlink()");
168 /* shm_open() after unlink/close should fail */
169 fd2
= shm_open(maxname
, O_RDWR
, S_IRUSR
| S_IWUSR
);
171 T_EXPECT_EQ(fd2
, -1, "shm_open() but removed");
172 T_EXPECT_EQ(errno
, ENOENT
, "Expected ENOENT");
175 * second phase of tests, try to create race conditions for
176 * shm_open() - multiple threads do shm_open(, ... O_EXCL, ...)
177 * ftruncate() - multiple threads, only 1 should succeed.
178 * fclose() - multiple threads, only 1 should succeed.
179 * shm_unlink() - multiple threads, only 1 should succeed.
183 T_LOG("Race testing shm_open");
184 atomic_fetch_add(&phase
, 1);
185 while (pass_count
+ fail_count
< nthreads
) {
188 T_EXPECT_EQ(pass_count
, 1, "racing shm_open()");
189 T_EXPECT_EQ(fail_count
, nthreads
- 1, "racing shm_open()");
191 atomic_store(&pass_count
, 0);
192 atomic_store(&fail_count
, 0);
193 T_LOG("Race testing ftruncate\n");
194 atomic_fetch_add(&phase
, 1);
195 while (pass_count
+ fail_count
< nthreads
) {
198 T_EXPECT_EQ(pass_count
, 1, "racing ftruncate()");
199 T_EXPECT_EQ(fail_count
, nthreads
- 1, "racing ftruncate()");
201 atomic_store(&pass_count
, 0);
202 atomic_store(&fail_count
, 0);
203 T_LOG("Race testing fclose\n");
204 atomic_fetch_add(&phase
, 1);
205 while (pass_count
+ fail_count
< nthreads
) {
208 T_EXPECT_EQ(pass_count
, 1, "racing fclose()");
209 T_EXPECT_EQ(fail_count
, nthreads
- 1, "racing fclose()");
211 atomic_store(&pass_count
, 0);
212 atomic_store(&fail_count
, 0);
213 T_LOG("Race testing shm_unlink\n");
214 atomic_fetch_add(&phase
, 1);
215 while (pass_count
+ fail_count
< nthreads
) {
218 T_EXPECT_EQ(pass_count
, 1, "racing shm_unlink()");
219 T_EXPECT_EQ(fail_count
, nthreads
- 1, "racing shm_unlink()");