1N/A/*
1N/A * Copyright (c) 2000-2002, 2004, 2005 Sendmail, Inc. and its suppliers.
1N/A * All rights reserved.
1N/A *
1N/A * By using this file, you agree to the terms and conditions set
1N/A * forth in the LICENSE file which can be found at the top level of
1N/A * the sendmail distribution.
1N/A */
1N/A
1N/A#pragma ident "%Z%%M% %I% %E% SMI"
1N/A
1N/A#include <sm/gen.h>
1N/ASM_RCSID("@(#)$Id: t-shm.c,v 1.22 2005/01/14 02:14:10 ca Exp $")
1N/A
1N/A#include <stdio.h>
1N/A
1N/A#if SM_CONF_SHM
1N/A# include <stdlib.h>
1N/A# include <unistd.h>
1N/A# include <sys/wait.h>
1N/A
1N/A# include <sm/heap.h>
1N/A# include <sm/string.h>
1N/A# include <sm/test.h>
1N/A# include <sm/shm.h>
1N/A
1N/A# define SHMSIZE 1024
1N/A# define SHM_MAX 6400000
1N/A# define T_SHMKEY 21
1N/A
1N/A
1N/A/*
1N/A** SHMINTER -- interactive testing of shared memory
1N/A**
1N/A** Parameters:
1N/A** owner -- create segment.
1N/A**
1N/A** Returns:
1N/A** 0 on success
1N/A** < 0 on failure.
1N/A*/
1N/A
1N/Aint shminter __P((bool));
1N/A
1N/Aint
1N/Ashminter(owner)
1N/A bool owner;
1N/A{
1N/A int *shm, shmid;
1N/A int i, t;
1N/A
1N/A shm = (int *) sm_shmstart(T_SHMKEY, SHMSIZE, 0, &shmid, owner);
1N/A if (shm == (int *) 0)
1N/A {
1N/A perror("shminit failed");
1N/A return -1;
1N/A }
1N/A
1N/A while ((t = getchar()) != EOF)
1N/A {
1N/A switch (t)
1N/A {
1N/A case 'c':
1N/A *shm = 0;
1N/A break;
1N/A case 'i':
1N/A ++*shm;
1N/A break;
1N/A case 'd':
1N/A --*shm;
1N/A break;
1N/A case 's':
1N/A sleep(1);
1N/A break;
1N/A case 'l':
1N/A t = *shm;
1N/A for (i = 0; i < SHM_MAX; i++)
1N/A {
1N/A ++*shm;
1N/A }
1N/A if (*shm != SHM_MAX + t)
1N/A fprintf(stderr, "error: %d != %d\n",
1N/A *shm, SHM_MAX + t);
1N/A break;
1N/A case 'v':
1N/A printf("shmval: %d\n", *shm);
1N/A break;
1N/A case 'S':
1N/A i = sm_shmsetowner(shmid, getuid(), getgid(), 0644);
1N/A printf("sm_shmsetowner=%d\n", i);
1N/A break;
1N/A }
1N/A }
1N/A return sm_shmstop((void *) shm, shmid, owner);
1N/A}
1N/A
1N/A
1N/A/*
1N/A** SHMBIG -- testing of shared memory
1N/A**
1N/A** Parameters:
1N/A** owner -- create segment.
1N/A** size -- size of segment.
1N/A**
1N/A** Returns:
1N/A** 0 on success
1N/A** < 0 on failure.
1N/A*/
1N/A
1N/Aint shmbig __P((bool, int));
1N/A
1N/Aint
1N/Ashmbig(owner, size)
1N/A bool owner;
1N/A int size;
1N/A{
1N/A int *shm, shmid;
1N/A int i;
1N/A
1N/A shm = (int *) sm_shmstart(T_SHMKEY, size, 0, &shmid, owner);
1N/A if (shm == (int *) 0)
1N/A {
1N/A perror("shminit failed");
1N/A return -1;
1N/A }
1N/A
1N/A for (i = 0; i < size / sizeof(int); i++)
1N/A shm[i] = i;
1N/A for (i = 0; i < size / sizeof(int); i++)
1N/A {
1N/A if (shm[i] != i)
1N/A {
1N/A fprintf(stderr, "failed at %d: %d", i, shm[i]);
1N/A }
1N/A }
1N/A
1N/A return sm_shmstop((void *) shm, shmid, owner);
1N/A}
1N/A
1N/A
1N/A/*
1N/A** SHMTEST -- test of shared memory
1N/A**
1N/A** Parameters:
1N/A** owner -- create segment.
1N/A**
1N/A** Returns:
1N/A** 0 on success
1N/A** < 0 on failure.
1N/A*/
1N/A
1N/A# define MAX_CNT 10
1N/A
1N/Aint shmtest __P((int));
1N/A
1N/Aint
1N/Ashmtest(owner)
1N/A int owner;
1N/A{
1N/A int *shm, shmid;
1N/A int cnt = 0;
1N/A
1N/A shm = (int *) sm_shmstart(T_SHMKEY, SHMSIZE, 0, &shmid, owner);
1N/A if (shm == (int *) 0)
1N/A {
1N/A perror("shminit failed");
1N/A return -1;
1N/A }
1N/A
1N/A if (owner)
1N/A {
1N/A int r;
1N/A
1N/A r = sm_shmsetowner(shmid, getuid(), getgid(), 0660);
1N/A SM_TEST(r == 0);
1N/A *shm = 1;
1N/A while (*shm == 1 && cnt++ < MAX_CNT)
1N/A sleep(1);
1N/A SM_TEST(cnt <= MAX_CNT);
1N/A
1N/A /* release and re-acquire the segment */
1N/A r = sm_shmstop((void *) shm, shmid, owner);
1N/A SM_TEST(r == 0);
1N/A shm = (int *) sm_shmstart(T_SHMKEY, SHMSIZE, 0, &shmid, owner);
1N/A SM_TEST(shm != (int *) 0);
1N/A }
1N/A else
1N/A {
1N/A while (*shm != 1 && cnt++ < MAX_CNT)
1N/A sleep(1);
1N/A SM_TEST(cnt <= MAX_CNT);
1N/A *shm = 2;
1N/A
1N/A /* wait a momemt so the segment is still in use */
1N/A sleep(2);
1N/A }
1N/A return sm_shmstop((void *) shm, shmid, owner);
1N/A}
1N/A
1N/Aint
1N/Amain(argc, argv)
1N/A int argc;
1N/A char *argv[];
1N/A{
1N/A bool interactive = false;
1N/A bool owner = false;
1N/A int big = -1;
1N/A int ch;
1N/A int r = 0;
1N/A int status;
1N/A extern char *optarg;
1N/A
1N/A# define OPTIONS "b:io"
1N/A while ((ch = getopt(argc, argv, OPTIONS)) != -1)
1N/A {
1N/A switch ((char) ch)
1N/A {
1N/A case 'b':
1N/A big = atoi(optarg);
1N/A break;
1N/A
1N/A case 'i':
1N/A interactive = true;
1N/A break;
1N/A
1N/A case 'o':
1N/A owner = true;
1N/A break;
1N/A
1N/A default:
1N/A break;
1N/A }
1N/A }
1N/A
1N/A if (interactive)
1N/A r = shminter(owner);
1N/A else if (big > 0)
1N/A r = shmbig(true, big);
1N/A else
1N/A {
1N/A pid_t pid;
1N/A extern int SmTestNumErrors;
1N/A
1N/A if ((pid = fork()) < 0)
1N/A {
1N/A perror("fork failed\n");
1N/A return -1;
1N/A }
1N/A
1N/A sm_test_begin(argc, argv, "test shared memory");
1N/A if (pid == 0)
1N/A {
1N/A /* give the parent the chance to setup data */
1N/A sleep(1);
1N/A r = shmtest(false);
1N/A }
1N/A else
1N/A {
1N/A r = shmtest(true);
1N/A (void) wait(&status);
1N/A }
1N/A SM_TEST(r == 0);
1N/A if (SmTestNumErrors > 0)
1N/A printf("add -DSM_CONF_SHM=0 to confENVDEF in devtools/Site/site.config.m4\nand start over.\n");
1N/A return sm_test_end();
1N/A }
1N/A return r;
1N/A}
1N/A#else /* SM_CONF_SHM */
1N/Aint
1N/Amain(argc, argv)
1N/A int argc;
1N/A char *argv[];
1N/A{
1N/A printf("No support for shared memory configured on this machine\n");
1N/A return 0;
1N/A}
1N/A#endif /* SM_CONF_SHM */