return get_errno(connect(sockfd, addr, addrlen));
}
-/* do_sendrecvmsg() Must return target values and target errnos. */
-static abi_long do_sendrecvmsg(int fd, abi_ulong target_msg,
- int flags, int send)
+/* do_sendrecvmsg_locked() Must return target values and target errnos. */
+static abi_long do_sendrecvmsg_locked(int fd, struct target_msghdr *msgp,
+ int flags, int send)
{
abi_long ret, len;
- struct target_msghdr *msgp;
struct msghdr msg;
int count;
struct iovec *vec;
abi_ulong target_vec;
- /* FIXME */
- if (!lock_user_struct(send ? VERIFY_READ : VERIFY_WRITE,
- msgp,
- target_msg,
- send ? 1 : 0))
- return -TARGET_EFAULT;
if (msgp->msg_name) {
msg.msg_namelen = tswap32(msgp->msg_namelen);
msg.msg_name = alloca(msg.msg_namelen);
out:
unlock_iovec(vec, target_vec, count, !send);
out2:
+ return ret;
+}
+
+static abi_long do_sendrecvmsg(int fd, abi_ulong target_msg,
+ int flags, int send)
+{
+ abi_long ret;
+ struct target_msghdr *msgp;
+
+ if (!lock_user_struct(send ? VERIFY_READ : VERIFY_WRITE,
+ msgp,
+ target_msg,
+ send ? 1 : 0)) {
+ return -TARGET_EFAULT;
+ }
+ ret = do_sendrecvmsg_locked(fd, msgp, flags, send);
unlock_user_struct(msgp, target_msg, send ? 0 : 1);
return ret;
}
+#ifdef TARGET_NR_sendmmsg
+/* We don't rely on the C library to have sendmmsg/recvmmsg support,
+ * so it might not have this *mmsg-specific flag either.
+ */
+#ifndef MSG_WAITFORONE
+#define MSG_WAITFORONE 0x10000
+#endif
+
+static abi_long do_sendrecvmmsg(int fd, abi_ulong target_msgvec,
+ unsigned int vlen, unsigned int flags,
+ int send)
+{
+ struct target_mmsghdr *mmsgp;
+ abi_long ret = 0;
+ int i;
+
+ if (vlen > UIO_MAXIOV) {
+ vlen = UIO_MAXIOV;
+ }
+
+ mmsgp = lock_user(VERIFY_WRITE, target_msgvec, sizeof(*mmsgp) * vlen, 1);
+ if (!mmsgp) {
+ return -TARGET_EFAULT;
+ }
+
+ for (i = 0; i < vlen; i++) {
+ ret = do_sendrecvmsg_locked(fd, &mmsgp[i].msg_hdr, flags, send);
+ if (is_error(ret)) {
+ break;
+ }
+ mmsgp[i].msg_len = tswap32(ret);
+ /* MSG_WAITFORONE turns on MSG_DONTWAIT after one packet */
+ if (flags & MSG_WAITFORONE) {
+ flags |= MSG_DONTWAIT;
+ }
+ }
+
+ unlock_user(mmsgp, target_msgvec, sizeof(*mmsgp) * i);
+
+ /* Return number of datagrams sent if we sent any at all;
+ * otherwise return the error.
+ */
+ if (i) {
+ return i;
+ }
+ return ret;
+}
+#endif
+
/* If we don't have a system accept4() then just call accept.
* The callsites to do_accept4() will ensure that they don't
* pass a non-zero flags argument in this config.
env = info->env;
cpu = ENV_GET_CPU(env);
thread_cpu = cpu;
- ts = (TaskState *)env->opaque;
+ ts = (TaskState *)cpu->opaque;
info->tid = gettid();
cpu->host_tid = info->tid;
task_settid(ts);
abi_ulong parent_tidptr, target_ulong newtls,
abi_ulong child_tidptr)
{
+ CPUState *cpu = ENV_GET_CPU(env);
int ret;
TaskState *ts;
+ CPUState *new_cpu;
CPUArchState *new_env;
unsigned int nptl_flags;
sigset_t sigmask;
flags &= ~(CLONE_VFORK | CLONE_VM);
if (flags & CLONE_VM) {
- TaskState *parent_ts = (TaskState *)env->opaque;
+ TaskState *parent_ts = (TaskState *)cpu->opaque;
new_thread_info info;
pthread_attr_t attr;
new_env = cpu_copy(env);
/* Init regs that differ from the parent. */
cpu_clone_regs(new_env, newsp);
- new_env->opaque = ts;
+ new_cpu = ENV_GET_CPU(new_env);
+ new_cpu->opaque = ts;
ts->bprm = parent_ts->bprm;
ts->info = parent_ts->info;
nptl_flags = flags;
put_user_u32(gettid(), child_tidptr);
if (flags & CLONE_PARENT_SETTID)
put_user_u32(gettid(), parent_tidptr);
- ts = (TaskState *)env->opaque;
+ ts = (TaskState *)cpu->opaque;
if (flags & CLONE_SETTLS)
cpu_set_tls (env, newtls);
if (flags & CLONE_CHILD_CLEARTID)
{
return tswap16(id);
}
+
+#define put_user_id(x, gaddr) put_user_u16(x, gaddr)
+
#else /* !USE_UID16 */
static inline int high2lowuid(int uid)
{
{
return tswap32(id);
}
+
+#define put_user_id(x, gaddr) put_user_u32(x, gaddr)
+
#endif /* USE_UID16 */
void syscall_init(void)
static int open_self_maps(void *cpu_env, int fd)
{
#if defined(TARGET_ARM) || defined(TARGET_M68K) || defined(TARGET_UNICORE32)
- TaskState *ts = ((CPUArchState *)cpu_env)->opaque;
+ CPUState *cpu = ENV_GET_CPU((CPUArchState *)cpu_env);
+ TaskState *ts = cpu->opaque;
#endif
FILE *fp;
char *line = NULL;
static int open_self_stat(void *cpu_env, int fd)
{
- TaskState *ts = ((CPUArchState *)cpu_env)->opaque;
+ CPUState *cpu = ENV_GET_CPU((CPUArchState *)cpu_env);
+ TaskState *ts = cpu->opaque;
abi_ulong start_stack = ts->info->start_stack;
int i;
static int open_self_auxv(void *cpu_env, int fd)
{
- TaskState *ts = ((CPUArchState *)cpu_env)->opaque;
+ CPUState *cpu = ENV_GET_CPU((CPUArchState *)cpu_env);
+ TaskState *ts = cpu->opaque;
abi_ulong auxv = ts->info->saved_auxv;
abi_ulong len = ts->info->auxv_len;
char *ptr;
/* Remove the CPU from the list. */
QTAILQ_REMOVE(&cpus, cpu, node);
cpu_list_unlock();
- ts = ((CPUArchState *)cpu_env)->opaque;
+ ts = cpu->opaque;
if (ts->child_tidptr) {
put_user_u32(0, ts->child_tidptr);
sys_futex(g2h(ts->child_tidptr), FUTEX_WAKE, INT_MAX,
NULL, NULL, 0);
}
thread_cpu = NULL;
- object_unref(OBJECT(ENV_GET_CPU(cpu_env)));
+ object_unref(OBJECT(cpu));
g_free(ts);
pthread_exit(NULL);
}
puts = NULL;
}
ret = get_errno(sigtimedwait(&set, &uinfo, puts));
- if (!is_error(ret) && arg2) {
- if (!(p = lock_user(VERIFY_WRITE, arg2, sizeof(target_siginfo_t), 0)))
- goto efault;
- host_to_target_siginfo(p, &uinfo);
- unlock_user(p, arg2, sizeof(target_siginfo_t));
+ if (!is_error(ret)) {
+ if (arg2) {
+ p = lock_user(VERIFY_WRITE, arg2, sizeof(target_siginfo_t),
+ 0);
+ if (!p) {
+ goto efault;
+ }
+ host_to_target_siginfo(p, &uinfo);
+ unlock_user(p, arg2, sizeof(target_siginfo_t));
+ }
+ ret = host_to_target_signal(ret);
}
}
break;
break;
case TARGET_NR_mprotect:
{
- TaskState *ts = ((CPUArchState *)cpu_env)->opaque;
+ TaskState *ts = cpu->opaque;
/* Special hack to detect libc making the stack executable. */
if ((arg3 & PROT_GROWSDOWN)
&& arg1 >= ts->info->stack_limit
ret = do_sendrecvmsg(arg1, arg2, arg3, 1);
break;
#endif
+#ifdef TARGET_NR_sendmmsg
+ case TARGET_NR_sendmmsg:
+ ret = do_sendrecvmmsg(arg1, arg2, arg3, arg4, 1);
+ break;
+ case TARGET_NR_recvmmsg:
+ ret = do_sendrecvmmsg(arg1, arg2, arg3, arg4, 0);
+ break;
+#endif
#ifdef TARGET_NR_sendto
case TARGET_NR_sendto:
ret = do_sendto(arg1, arg2, arg3, arg4, arg5, arg6);
uid_t ruid, euid, suid;
ret = get_errno(getresuid(&ruid, &euid, &suid));
if (!is_error(ret)) {
- if (put_user_u16(high2lowuid(ruid), arg1)
- || put_user_u16(high2lowuid(euid), arg2)
- || put_user_u16(high2lowuid(suid), arg3))
+ if (put_user_id(high2lowuid(ruid), arg1)
+ || put_user_id(high2lowuid(euid), arg2)
+ || put_user_id(high2lowuid(suid), arg3))
goto efault;
}
}
gid_t rgid, egid, sgid;
ret = get_errno(getresgid(&rgid, &egid, &sgid));
if (!is_error(ret)) {
- if (put_user_u16(high2lowgid(rgid), arg1)
- || put_user_u16(high2lowgid(egid), arg2)
- || put_user_u16(high2lowgid(sgid), arg3))
+ if (put_user_id(high2lowgid(rgid), arg1)
+ || put_user_id(high2lowgid(egid), arg2)
+ || put_user_id(high2lowgid(sgid), arg3))
goto efault;
}
}
break;
#elif defined(TARGET_M68K)
{
- TaskState *ts = ((CPUArchState *)cpu_env)->opaque;
+ TaskState *ts = cpu->opaque;
ts->tp_value = arg1;
ret = 0;
break;
break;
#elif defined(TARGET_M68K)
{
- TaskState *ts = ((CPUArchState *)cpu_env)->opaque;
+ TaskState *ts = cpu->opaque;
ret = ts->tp_value;
break;
}