Home | History | Annotate | Download | only in pthread_mutex_init
      1 /*
      2  * Copyright (c) 2004, Bull S.A..  All rights reserved.
      3  * Created by: Sebastien Decugis
      4 
      5  * This program is free software; you can redistribute it and/or modify it
      6  * under the terms of version 2 of the GNU General Public License as
      7  * published by the Free Software Foundation.
      8  *
      9  * This program is distributed in the hope that it would be useful, but
     10  * WITHOUT ANY WARRANTY; without even the implied warranty of
     11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
     12  *
     13  * You should have received a copy of the GNU General Public License along
     14  * with this program; if not, write the Free Software Foundation, Inc.,
     15  * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
     16  *
     17 
     18  * This sample test aims to check the following assertion:
     19  * The function fails and returns ENOMEM if there is not enough memory.
     20 
     21  * The steps are:
     22  * * Fork
     23  * * New process sets its memory resource limit to a minimum value, then
     24  *  -> Allocate all the available memory
     25  *  -> call pthread_mutex_init()
     26  *  -> free the memory
     27  *  -> Checks that pthread_mutex_init() returned 0 or ENOMEM.
     28  * * Parent process waits for the child.
     29  */
     30 
     31  /* We are testing conformance to IEEE Std 1003.1, 2003 Edition */
     32 #define _POSIX_C_SOURCE 200112L
     33 
     34  /* We need the setrlimit() function from X/OPEN standard */
     35 #ifndef WITHOUT_XOPEN
     36 #define _XOPEN_SOURCE	600
     37 
     38 /********************************************************************************************/
     39 /****************************** standard includes *****************************************/
     40 /********************************************************************************************/
     41 #include <pthread.h>
     42 #include <stdio.h>
     43 #include <unistd.h>
     44 #include <stdlib.h>
     45 #include <errno.h>
     46 #include <signal.h>
     47 #include <sys/wait.h>
     48 #include <sys/resource.h>
     49 #include <stdarg.h>
     50 
     51 /********************************************************************************************/
     52 /******************************   Test framework   *****************************************/
     53 /********************************************************************************************/
     54 #include "../testfrmw/testfrmw.h"
     55 #include "../testfrmw/testfrmw.c"
     56  /* This header is responsible for defining the following macros:
     57   * UNRESOLVED(ret, descr);
     58   *    where descr is a description of the error and ret is an int (error code for example)
     59   * FAILED(descr);
     60   *    where descr is a short text saying why the test has failed.
     61   * PASSED();
     62   *    No parameter.
     63   *
     64   * Both three macros shall terminate the calling process.
     65   * The testcase shall not terminate in any other maneer.
     66   *
     67   * The other file defines the functions
     68   * void output_init()
     69   * void output(char * string, ...)
     70   *
     71   * Those may be used to output information.
     72   */
     73 
     74 /********************************************************************************************/
     75 /********************************** Configuration ******************************************/
     76 /********************************************************************************************/
     77 #ifndef VERBOSE
     78 #define VERBOSE 1
     79 #endif
     80 
     81 /********************************************************************************************/
     82 /***********************************    Test case   *****************************************/
     83 /********************************************************************************************/
     84 
     85 int main(void)
     86 {
     87 	pid_t child;
     88 
     89 	pthread_mutex_t mtx;
     90 	pthread_mutexattr_t ma[4];
     91 	pthread_mutexattr_t *pma[5];
     92 
     93 	int ret = 0;
     94 	int i;
     95 	int retini[5] = { -1, -1, -1, -1, -1 };
     96 	int retdtr[5] = { -1, -1, -1, -1, -1 };
     97 
     98 	void *ptr, *ptr_prev = NULL;
     99 
    100 	int sz = 0;
    101 	struct rlimit rl;
    102 
    103 	int status = 0;
    104 
    105 	output_init();
    106 
    107 	child = fork();
    108 
    109 	if (child == (pid_t) - 1) {
    110 		UNRESOLVED(errno, "Fork failed");
    111 	}
    112 
    113 	if (child != 0) {	/* We are the father */
    114 		if (child != waitpid(child, &status, 0)) {
    115 			UNRESOLVED(errno, "Waitpid failed");
    116 		}
    117 
    118 		if (WIFSIGNALED(status)) {
    119 			UNRESOLVED(WTERMSIG(status),
    120 				   "The child process was killed.");
    121 		}
    122 
    123 		if (WIFEXITED(status))
    124 			return WEXITSTATUS(status);
    125 
    126 		UNRESOLVED(0, "Child process neither returned nor was killed.");
    127 	}
    128 
    129 	/* Only the child goes further */
    130 
    131 	/* We initialize the different mutex attributes */
    132 	for (i = 0; (i < 4) && (ret == 0); i++) {
    133 		pma[i] = &ma[i];
    134 		ret = pthread_mutexattr_init(pma[i]);
    135 	}
    136 	if (ret) {
    137 		UNRESOLVED(ret, "Mutex attribute init failed");
    138 	}
    139 	pma[4] = NULL;
    140 
    141 	if ((ret = pthread_mutexattr_settype(pma[0], PTHREAD_MUTEX_NORMAL))) {
    142 		UNRESOLVED(ret, "Mutex attribute NORMAL failed");
    143 	}
    144 	if ((ret = pthread_mutexattr_settype(pma[0], PTHREAD_MUTEX_DEFAULT))) {
    145 		UNRESOLVED(ret, "Mutex attribute DEFAULT failed");
    146 	}
    147 	if ((ret = pthread_mutexattr_settype(pma[0], PTHREAD_MUTEX_RECURSIVE))) {
    148 		UNRESOLVED(ret, "Mutex attribute RECURSIVE failed");
    149 	}
    150 	if ((ret = pthread_mutexattr_settype(pma[0], PTHREAD_MUTEX_ERRORCHECK))) {
    151 		UNRESOLVED(ret, "Mutex attribute ERRORCHECK failed");
    152 	}
    153 
    154 	sz = sysconf(_SC_PAGESIZE);
    155 
    156 	/* Limit the process memory to a small value (64Mb for example). */
    157 	rl.rlim_max = 1024 * 1024 * 64;
    158 	rl.rlim_cur = 1024 * 1024 * 64;
    159 	if ((ret = setrlimit(RLIMIT_AS, &rl))) {
    160 		UNRESOLVED(ret, "Memory limitation failed");
    161 	}
    162 #if VERBOSE > 1
    163 	output("Ready to take over memory. Page size is %d\n", sz);
    164 #endif
    165 
    166 	/* Allocate all available memory */
    167 	while (1) {
    168 		ptr = malloc(sz);	/* Allocate one page of memory */
    169 		if (ptr == NULL)
    170 			break;
    171 #if VERBOSE > 1
    172 		ret++;
    173 #endif
    174 		*(void **)ptr = ptr_prev;	/* Write into the allocated page */
    175 		ptr_prev = ptr;
    176 	}
    177 #if VERBOSE > 1
    178 	output("%d pages were allocated before failure\n", ret);
    179 	ret = 0;
    180 #endif
    181 
    182 	while (1) {
    183 		ptr = malloc(sizeof(void *));	/* Allocate every remaining bits of memory */
    184 		if (ptr == NULL)
    185 			break;
    186 #if VERBOSE > 1
    187 		ret++;
    188 #endif
    189 		*(void **)ptr = ptr_prev;	/* Keep track of allocated memory */
    190 		ptr_prev = ptr;
    191 	}
    192 #if VERBOSE > 1
    193 	output("%d additional spaces were allocated before failure\n", ret);
    194 	ret = 0;
    195 #endif
    196 	if (errno != ENOMEM)
    197 		UNRESOLVED(errno, "Memory not full");
    198 
    199 	/* Now that memory is full, we try to initialize a mutex */
    200 	for (i = 0; i < 5; i++) {
    201 		retini[i] = pthread_mutex_init(&mtx, pma[i]);
    202 		if (!retini[i])	/* If mutex has been initialized, we destroy it */
    203 			retdtr[i] = pthread_mutex_destroy(&mtx);
    204 	}
    205 
    206 	/* We can now free the memory */
    207 	while (ptr_prev != NULL) {
    208 		ptr = ptr_prev;
    209 		ptr_prev = *(void **)ptr;
    210 		free(ptr);
    211 	}
    212 
    213 #if VERBOSE > 1
    214 	output("Memory is released\n");
    215 #endif
    216 
    217 	for (i = 0; i < 4; i++)
    218 		pthread_mutexattr_destroy(pma[i]);
    219 
    220 	for (i = 0; i < 5; i++) {
    221 		if (retini[i] != 0 && retini[i] != ENOMEM) {
    222 			FAILED
    223 			    ("Mutex init returned a wrong error code when no memory was left");
    224 		}
    225 
    226 		if (retini[i] == 0) {
    227 #if VERBOSE > 0
    228 			output
    229 			    ("Mutex initialization for attribute %d succeeds when memory is full\n",
    230 			     i);
    231 #endif
    232 			if (retdtr[i] != 0) {
    233 				UNRESOLVED(retdtr[i],
    234 					   "Mutex destroy failed on mutex inilialized under heavy loaded memory");
    235 			}
    236 		}
    237 #if VERBOSE > 0
    238 		else {
    239 			output
    240 			    ("Mutex initialization for attribute %d fails with ENOMEM when memory is full\n",
    241 			     i);
    242 		}
    243 #endif
    244 	}
    245 	PASSED;
    246 }
    247 
    248 #else /* WITHOUT_XOPEN */
    249 int main(void)
    250 {
    251 	output_init();
    252 	UNTESTED("This test requires XSI features");
    253 }
    254 #endif
    255