| /* |
| * Copyright (C) 2010 Red Hat, Inc. |
| * |
| * This program is free software; you can redistribute it and/or modify |
| * it under the terms of version 2 of the GNU General Public License as |
| * published by the Free Software Foundation. |
| * |
| * This program is distributed in the hope that it would be useful, but |
| * WITHOUT ANY WARRANTY; without even the implied warranty of |
| * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. |
| * |
| * Further, this software is distributed without any warranty that it is |
| * free of the rightful claim of any third person regarding infringement |
| * or the like. Any license provided herein, whether implied or |
| * otherwise, applies only to this software file. Patent licenses, if |
| * any, provided herein do not apply to combinations of this program |
| * with other software, or any other product whatsoever. |
| * |
| * You should have received a copy of the GNU General Public License |
| * along with this program; if not, write the Free Software Foundation, |
| * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. |
| */ |
| /* |
| * munmap() don't check sysctl_max_mapcount |
| * |
| * From http://lkml.org/lkml/2009/10/2/85: |
| * |
| * On ia64, the following test program exit abnormally, because glibc |
| * thread library called abort(). |
| * |
| * ======================================================== |
| * (gdb) bt |
| * #0 0xa000000000010620 in __kernel_syscall_via_break () |
| * #1 0x20000000003208e0 in raise () from /lib/libc.so.6.1 |
| * #2 0x2000000000324090 in abort () from /lib/libc.so.6.1 |
| * #3 0x200000000027c3e0 in __deallocate_stack () from |
| * /lib/libpthread.so.0 |
| * #4 0x200000000027f7c0 in start_thread () from /lib/libpthread.so.0 |
| * #5 0x200000000047ef60 in __clone2 () from /lib/libc.so.6.1 |
| * ======================================================== |
| * The fact is, glibc call munmap() when thread exitng time for freeing |
| * stack, and it assume munlock() never fail. However, munmap() often |
| * make vma splitting and it with many mapcount make -ENOMEM. |
| * |
| * Oh well, stack unfreeing is not reasonable option. Also munlock() via |
| * free() shouldn't failed. |
| * |
| * Thus, munmap() shoudn't check max-mapcount. |
| */ |
| #include<stdio.h> |
| #include<stdlib.h> |
| #include<string.h> |
| #include<pthread.h> |
| #include<errno.h> |
| #include<unistd.h> |
| #include "test.h" |
| |
| char *TCID = "mmap11"; |
| int TST_TOTAL = 1; |
| |
| #define MAL_SIZE (100*1024) |
| |
| static void *wait_thread(void *args); |
| static void *wait_thread2(void *args); |
| static void setup(void); |
| static void cleanup(void); |
| static void check(void); |
| |
| int main(int argc, char *argv[]) |
| { |
| const char *msg; |
| |
| msg = parse_opts(argc, argv, NULL, NULL); |
| if (msg != NULL) |
| tst_brkm(TBROK, NULL, "OPTION PARSING ERROR - %s", msg); |
| setup(); |
| check(); |
| cleanup(); |
| tst_exit(); |
| } |
| |
| void setup(void) |
| { |
| tst_require_root(NULL); |
| |
| tst_sig(FORK, DEF_HANDLER, cleanup); |
| TEST_PAUSE; |
| } |
| |
| void cleanup(void) |
| { |
| } |
| |
| void check(void) |
| { |
| int lc; |
| pthread_t *thread, th; |
| int ret, count = 0; |
| pthread_attr_t attr; |
| |
| ret = pthread_attr_init(&attr); |
| if (ret) |
| tst_brkm(TBROK | TERRNO, cleanup, "pthread_attr_init"); |
| ret = pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED); |
| if (ret) |
| tst_brkm(TBROK | TERRNO, cleanup, |
| "pthread_attr_setdetachstate"); |
| thread = malloc(STD_LOOP_COUNT * sizeof(pthread_t)); |
| if (thread == NULL) |
| tst_brkm(TBROK | TERRNO, cleanup, "malloc"); |
| |
| for (lc = 0; TEST_LOOPING(lc); lc++) { |
| tst_count = 0; |
| ret = pthread_create(&th, &attr, wait_thread, NULL); |
| if (ret) { |
| tst_resm(TINFO, "[%d] ", count); |
| tst_brkm(TBROK | TERRNO, cleanup, "pthread_create"); |
| } |
| count++; |
| ret = pthread_create(&thread[lc], &attr, wait_thread2, NULL); |
| if (ret) { |
| tst_resm(TINFO, "[%d] ", count); |
| tst_brkm(TBROK | TERRNO, cleanup, "pthread_create"); |
| } |
| count++; |
| } |
| tst_resm(TPASS, "test completed."); |
| free(thread); |
| } |
| |
| void *wait_thread(void *args) |
| { |
| void *addr; |
| |
| addr = malloc(MAL_SIZE); |
| if (addr) |
| memset(addr, 1, MAL_SIZE); |
| sleep(1); |
| return NULL; |
| } |
| |
| void *wait_thread2(void *args) |
| { |
| return NULL; |
| } |