blob: 93cdc436ccc490b0f272e3a9529bf6e159c447ef [file] [log] [blame]
vapierf6d7f092009-11-03 20:07:35 +00001/*
2 * Copyright (c) International Business Machines Corp., 2009
3 * Some wrappers for clone functionality. Thrown together by Serge Hallyn
4 * <serue@us.ibm.com> based on existing clone usage in ltp.
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
14 * the GNU General Public License for more details.
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
18 */
19
yaberauneya8680b282009-11-14 10:27:29 +000020#ifndef _GNU_SOURCE
vapierf6d7f092009-11-03 20:07:35 +000021#define _GNU_SOURCE
yaberauneya8680b282009-11-14 10:27:29 +000022#endif
vapierf6d7f092009-11-03 20:07:35 +000023
24#include <stdio.h>
25#include <errno.h>
26#include <unistd.h> /* fork, getpid, sleep */
27#include <string.h>
28#include <stdlib.h> /* exit */
29#include <sched.h> /* clone */
30#include "test.h"
31
32#undef clone /* we want to use clone() */
33
34/* copied from several other files under ltp */
35#if defined (__s390__) || (__s390x__)
36#define clone __clone
37extern int __clone(int(void*),void*,int,void*);
38#elif defined(__ia64__)
39#define clone2 __clone2
40/* Prototype provided by David Mosberger */
41extern int __clone2(int (*fn) (void *arg), void *child_stack_base,
42 size_t child_stack_size, int flags, void *arg,
43 pid_t *parent_tid, void *tls, pid_t *child_tid);
44#endif
45
46/***********************************************************************
47 * ltp_clone: wrapper for clone to hide the architecture dependencies.
48 * 1. hppa takes bottom of stack and no stacksize (stack grows up)
49 * 2. __ia64__ takes bottom of stack and uses clone2
50 * 3. all others take top of stack (stack grows down)
51 ***********************************************************************/
52int
53ltp_clone(unsigned long clone_flags, int (*fn)(void *arg), void *arg,
54 size_t stack_size, void *stack)
55{
56 int ret;
57
58#if defined(__hppa__)
59 ret = clone(fn, stack, clone_flags, arg);
60#elif defined(__ia64__)
61 ret = clone2(fn, stack, stack_size, clone_flags, arg, NULL, NULL, NULL);
62#else
63 ret = clone(fn, (stack ? stack + stack_size - 1 : NULL),
64 clone_flags, arg);
65#endif
66
67 return ret;
68}
69
70/***********************************************************************
71 * ltp_clone_malloc: also does the memory allocation for clone with a
72 * caller-specified size.
73 ***********************************************************************/
74int
75ltp_clone_malloc(unsigned long clone_flags, int (*fn)(void *arg), void *arg,
76 size_t stack_size)
77{
78 int ret;
79 void *stack = malloc(stack_size);
80 int saved_errno;
81
82 if (!stack)
83 return -1;
84
85 ret = ltp_clone(clone_flags, fn, arg, stack_size, stack);
86
87 if (ret == -1) {
88 saved_errno = errno;
89 free(stack);
90 errno = saved_errno;
91 }
92
93 return ret;
94}
95
96/***********************************************************************
97 * ltp_clone_quick: calls ltp_clone_malloc with predetermined stack size.
98 * Experience thus far suggests that one page is often insufficient,
99 * while 4*getpagesize() seems adequate.
100 ***********************************************************************/
101int
102ltp_clone_quick(unsigned long clone_flags, int (*fn)(void *arg), void *arg)
103{
104 size_t stack_size = getpagesize() * 4;
105
106 return ltp_clone_malloc(clone_flags, fn, arg, stack_size);
107}