|
@@ -40,11 +40,26 @@ int shim_do_sched_getaffinity (pid_t pid, size_t len,
|
|
|
__kernel_cpu_set_t * user_mask_ptr)
|
|
__kernel_cpu_set_t * user_mask_ptr)
|
|
|
{
|
|
{
|
|
|
int ncpus = PAL_CB(cpu_info.cpu_num);
|
|
int ncpus = PAL_CB(cpu_info.cpu_num);
|
|
|
- // Check that user_mask_ptr is valid; if not, should return -EFAULT
|
|
|
|
|
|
|
+
|
|
|
|
|
+ /* Check that user_mask_ptr is valid; if not, should return -EFAULT */
|
|
|
if (test_user_memory(user_mask_ptr, len, 1))
|
|
if (test_user_memory(user_mask_ptr, len, 1))
|
|
|
return -EFAULT;
|
|
return -EFAULT;
|
|
|
|
|
+
|
|
|
|
|
+ /* Linux kernel bitmap is based on long. So according to its
|
|
|
|
|
+ * implementation, round up the result to sizeof(long) */
|
|
|
|
|
+ int bitmask_long_count = (ncpus + sizeof(long) * 8 - 1) /
|
|
|
|
|
+ (sizeof(long) * 8);
|
|
|
|
|
+ int bitmask_size_in_bytes = bitmask_long_count * sizeof(long);
|
|
|
|
|
+ if (len < bitmask_size_in_bytes)
|
|
|
|
|
+ return -EINVAL;
|
|
|
|
|
+ /* Linux kernel also rejects non-natural size */
|
|
|
|
|
+ if (len & (sizeof(long) - 1))
|
|
|
|
|
+ return -EINVAL;
|
|
|
|
|
+
|
|
|
memset(user_mask_ptr, 0, len);
|
|
memset(user_mask_ptr, 0, len);
|
|
|
for (int i = 0 ; i < ncpus ; i++)
|
|
for (int i = 0 ; i < ncpus ; i++)
|
|
|
((uint8_t *) user_mask_ptr)[i / 8] |= 1 << (i % 8);
|
|
((uint8_t *) user_mask_ptr)[i / 8] |= 1 << (i % 8);
|
|
|
- return ncpus;
|
|
|
|
|
|
|
+ /* imitate the Linux kernel implementation
|
|
|
|
|
+ * See SYSCALL_DEFINE3(sched_getaffinity) */
|
|
|
|
|
+ return bitmask_size_in_bytes;
|
|
|
}
|
|
}
|