On 24/03/2017 18:11, Corinna Vinschen wrote:
Hi Noah,
On GNU/Linux, AIX, and Solaris, the processes keep busy and finish one million
lock/unlock cycles apiece in a few minutes. On Cygwin, they hang within a few
seconds and under one hundred cycles apiece. At that point, cygserver is
unresponsive to other clients; for example, "strace /bin/true", opening a new
Cygwin terminal, "cat /proc/sysvipc/sem" and "cygserver -S" all hang. In most
tests, cygserver was not consuming CPU while unresponsive.
I pushed a patchset now, and uploaded new developer snapshots for
testing to https://cygwin.com/snapshots/
I'm also going to create a 2.8.0-0.4 test release later today.
Please give it a try, and please note that *all* patches affect
cygserver itself, so you have to test the new cygserver in the
first place. The Cygwin DLL is not affected by the changes.
Thanks,
Corinna
Hi Corinna,
just noted a small glitch.
Attached a modification of Noah's test, it now accepts the number of
workers and semaphore are as before workers/4
./sema_parallel-2 32
worker ....
OK
./sema_parallel-2 64
semget
semget: Invalid argument
If I restart the cygserver
./sema_parallel-2 64
worker ....
OK
./sema_parallel-2 128
semget
semget: Invalid argument
It seems that the number of max available semaphores is frozen to first
call value.
/*
* Demonstrate cygserver hang under concurrent sysv semaphore traffic. Run
* without arguments. Output will cease within a few seconds, and cygserver
* will be unresponsive to all clients.
*
* This is compatible with default cygserver settings; it uses a single
* semaphore set of four semaphores.
*/
#include <errno.h>
#include <stdio.h>
#include <stdlib.h>
#include <sys/ipc.h>
#include <sys/sem.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <unistd.h>
#define SEM_KEY 0x631a2c3e
#define N_CYCLE 1000000
union semun
{
int val;
struct semid_ds *buf;
unsigned short *array;
};
static int print_every = 1;
/* In parallel, N_WORKER processes run this function. */
static int do_worker(int ordinal, int set, int N_SEMA)
{
int i;
struct sembuf op;
printf("start worker %d\n", ordinal);
fflush(stdout);
op.sem_flg = 0;
for (i = 1; i <= N_CYCLE; i++)
{
op.sem_num = random() % N_SEMA;
op.sem_op = -1;
if (0 > semop(set, &op, 1))
{
perror("semop");
return 1;
}
op.sem_op = 1;
if (0 > semop(set, &op, 1))
{
perror("semop");
return 1;
}
if (i % print_every == 0)
{
printf("worker %d: %d cycles elapsed\n", ordinal, i);
fflush(stdout);
}
}
return 0;
}
int main(int argc, char **argv)
{
int status = 1, set, i, child_status;
int N_WORKER, N_SEMA;
switch(argc){
case 3:
print_every = atoi(argv[2]);
case 2:
N_WORKER=atoi(argv[1]);
N_SEMA= (N_WORKER/4);
break;
default:
fprintf(stderr, "Usage: sema_parallel workers [print-every-N]\n");
return status;
}
puts("semget");
fflush(stdout);
set = semget(SEM_KEY, N_SEMA, IPC_CREAT | 0600);
if (set == -1)
{
perror("semget");
return status;
}
puts("SETVAL");
fflush(stdout);
for (i = 0; i < N_SEMA; i++)
{
union semun s;
s.val = 1;
if (0 > semctl(set, i, SETVAL, s))
{
perror("semctl(SETVAL)");
goto cleanup;
}
}
for (i = 0; i < N_WORKER; i++)
{
pid_t pid;
pid = fork();
switch (pid)
{
case -1:
perror("fork");
goto cleanup;
case 0:
return do_worker(i, set, N_SEMA );
}
}
status = 0;
cleanup:
while (wait(&child_status) != -1)
;
if (errno != ECHILD)
{
perror("wait");
status = 1;
}
if (0 > semctl(set, 0, IPC_RMID))
{
perror("semtctl(IPC_RMID)");
status = 1;
}
return status;
}
--
Problem reports: http://cygwin.com/problems.html
FAQ: http://cygwin.com/faq/
Documentation: http://cygwin.com/docs.html
Unsubscribe info: http://cygwin.com/ml/#unsubscribe-simple