@samitouri / QOSamiQemu / commits / 6cefbee70b

bsd-user: Add do_bsd___semctl implementation

Add implementation of __semctl(2) syscall for System V semaphore control operations. Handles command translation, endianness conversion for GETVAL/ SETVAL, and array/structure conversions for GETALL/SETALL/IPC_STAT/IPC_SET. Signed-off-by: Stacey Son <sson@FreeBSD.org> Reviewed-by: Pierrick Bouvier <pierrick.bouvier@linaro.org> Signed-off-by: Warner Losh <imp@bsdimp.com>

Stacey Son committed Feb 2, 2026 at 16:45 UTC 6cefbee70be2c256d58d534df0556907bd8c4ebd
1 file changed +114
bsd-user/bsd-misc.h
+114
@@ -99,6 +99,120 @@ static inline abi_long do_bsd_semop(int semid, abi_long ptr, unsigned nsops)
99 return semop(semid, sops, nsops);
100 }
101
102 +/* __semctl(2) */
103 +static inline abi_long do_bsd___semctl(int semid, int semnum, int target_cmd,
104 + abi_ptr un_ptr)
105 +{
106 + void *target_un;
107 + union semun arg;
108 + struct semid_ds dsarg;
109 + unsigned short *array = NULL;
110 + int host_cmd;
111 + abi_long ret = 0;
112 + abi_ulong target_array, target_buffer;
113 +
114 + switch (target_cmd) {
115 + case TARGET_GETVAL:
116 + host_cmd = GETVAL;
117 + break;
118 +
119 + case TARGET_SETVAL:
120 + host_cmd = SETVAL;
121 + break;
122 +
123 + case TARGET_GETALL:
124 + host_cmd = GETALL;
125 + break;
126 +
127 + case TARGET_SETALL:
128 + host_cmd = SETALL;
129 + break;
130 +
131 + case TARGET_IPC_STAT:
132 + host_cmd = IPC_STAT;
133 + break;
134 +
135 + case TARGET_IPC_SET:
136 + host_cmd = IPC_SET;
137 + break;
138 +
139 + case TARGET_IPC_RMID:
140 + host_cmd = IPC_RMID;
141 + break;
142 +
143 + case TARGET_GETPID:
144 + host_cmd = GETPID;
145 + break;
146 +
147 + case TARGET_GETNCNT:
148 + host_cmd = GETNCNT;
149 + break;
150 +
151 + case TARGET_GETZCNT:
152 + host_cmd = GETZCNT;
153 + break;
154 +
155 + default:
156 + return -TARGET_EINVAL;
157 + }
158 +
159 + /*
160 + * Unlike Linux and the semctl system call, we take a pointer
161 + * to the union arg here.
162 + */
163 + target_un = lock_user(VERIFY_READ, un_ptr, sizeof(union target_semun), 1);
164 +
165 + switch (host_cmd) {
166 + case GETVAL:
167 + case SETVAL:
168 + __get_user(arg.val, (abi_int *)target_un);
169 + ret = get_errno(semctl(semid, semnum, host_cmd, arg));
170 + break;
171 +
172 + case GETALL:
173 + case SETALL:
174 + __get_user(target_array, (abi_ulong *)target_un);
175 + ret = target_to_host_semarray(semid, &array, target_array);
176 + if (is_error(ret)) {
177 + goto out;
178 + }
179 + arg.array = array;
180 + ret = get_errno(semctl(semid, semnum, host_cmd, arg));
181 + if (!is_error(ret)) {
182 + ret = host_to_target_semarray(semid, target_array, &array);
183 + }
184 + break;
185 +
186 + case IPC_STAT:
187 + case IPC_SET:
188 + __get_user(target_buffer, (abi_ulong *)target_un);
189 + ret = target_to_host_semid_ds(&dsarg, target_buffer);
190 + if (is_error(ret)) {
191 + goto out;
192 + }
193 + arg.buf = &dsarg;
194 + ret = get_errno(semctl(semid, semnum, host_cmd, arg));
195 + if (!is_error(ret)) {
196 + ret = host_to_target_semid_ds(target_buffer, &dsarg);
197 + }
198 + break;
199 +
200 + case IPC_RMID:
201 + case GETPID:
202 + case GETNCNT:
203 + case GETZCNT:
204 + ret = get_errno(semctl(semid, semnum, host_cmd, NULL));
205 + break;
206 +
207 + default:
208 + ret = -TARGET_EINVAL;
209 + break;
210 + }
211 +out:
212 + unlock_user(target_un, un_ptr, 1);
213 + return ret;
214 +}
215 +
216 /* getdtablesize(2) */
217 static inline abi_long do_bsd_getdtablesize(void)
218 {