aboutsummaryrefslogtreecommitdiffstats
path: root/arch/um/kernel/sigio_user.c
diff options
context:
space:
mode:
Diffstat (limited to 'arch/um/kernel/sigio_user.c')
-rw-r--r--arch/um/kernel/sigio_user.c85
1 files changed, 60 insertions, 25 deletions
diff --git a/arch/um/kernel/sigio_user.c b/arch/um/kernel/sigio_user.c
index 48b1f644b9a6..f7b18e157d35 100644
--- a/arch/um/kernel/sigio_user.c
+++ b/arch/um/kernel/sigio_user.c
@@ -216,6 +216,8 @@ static int write_sigio_thread(void *unused)
216 "err = %d\n", -n); 216 "err = %d\n", -n);
217 } 217 }
218 } 218 }
219
220 return 0;
219} 221}
220 222
221static int need_poll(int n) 223static int need_poll(int n)
@@ -335,70 +337,103 @@ int ignore_sigio_fd(int fd)
335 return(err); 337 return(err);
336} 338}
337 339
338static int setup_initial_poll(int fd) 340static struct pollfd* setup_initial_poll(int fd)
339{ 341{
340 struct pollfd *p; 342 struct pollfd *p;
341 343
342 p = um_kmalloc_atomic(sizeof(struct pollfd)); 344 p = um_kmalloc(sizeof(struct pollfd));
343 if(p == NULL){ 345 if (p == NULL) {
344 printk("setup_initial_poll : failed to allocate poll\n"); 346 printk("setup_initial_poll : failed to allocate poll\n");
345 return(-1); 347 return NULL;
346 } 348 }
347 *p = ((struct pollfd) { .fd = fd, 349 *p = ((struct pollfd) { .fd = fd,
348 .events = POLLIN, 350 .events = POLLIN,
349 .revents = 0 }); 351 .revents = 0 });
350 current_poll = ((struct pollfds) { .poll = p, 352 return p;
351 .used = 1,
352 .size = 1 });
353 return(0);
354} 353}
355 354
356void write_sigio_workaround(void) 355void write_sigio_workaround(void)
357{ 356{
358 unsigned long stack; 357 unsigned long stack;
358 struct pollfd *p;
359 int err; 359 int err;
360 int l_write_sigio_fds[2];
361 int l_sigio_private[2];
362 int l_write_sigio_pid;
360 363
364 /* We call this *tons* of times - and most ones we must just fail. */
361 sigio_lock(); 365 sigio_lock();
362 if(write_sigio_pid != -1) 366 l_write_sigio_pid = write_sigio_pid;
363 goto out; 367 sigio_unlock();
368
369 if (l_write_sigio_pid != -1)
370 return;
364 371
365 err = os_pipe(write_sigio_fds, 1, 1); 372 err = os_pipe(l_write_sigio_fds, 1, 1);
366 if(err < 0){ 373 if(err < 0){
367 printk("write_sigio_workaround - os_pipe 1 failed, " 374 printk("write_sigio_workaround - os_pipe 1 failed, "
368 "err = %d\n", -err); 375 "err = %d\n", -err);
369 goto out; 376 return;
370 } 377 }
371 err = os_pipe(sigio_private, 1, 1); 378 err = os_pipe(l_sigio_private, 1, 1);
372 if(err < 0){ 379 if(err < 0){
373 printk("write_sigio_workaround - os_pipe 2 failed, " 380 printk("write_sigio_workaround - os_pipe 1 failed, "
374 "err = %d\n", -err); 381 "err = %d\n", -err);
375 goto out_close1; 382 goto out_close1;
376 } 383 }
377 if(setup_initial_poll(sigio_private[1])) 384
385 p = setup_initial_poll(l_sigio_private[1]);
386 if(!p)
378 goto out_close2; 387 goto out_close2;
379 388
380 write_sigio_pid = run_helper_thread(write_sigio_thread, NULL, 389 sigio_lock();
390
391 /* Did we race? Don't try to optimize this, please, it's not so likely
392 * to happen, and no more than once at the boot. */
393 if(write_sigio_pid != -1)
394 goto out_unlock;
395
396 write_sigio_pid = run_helper_thread(write_sigio_thread, NULL,
381 CLONE_FILES | CLONE_VM, &stack, 0); 397 CLONE_FILES | CLONE_VM, &stack, 0);
382 398
383 if(write_sigio_pid < 0) goto out_close2; 399 if (write_sigio_pid < 0)
400 goto out_clear;
384 401
385 if(write_sigio_irq(write_sigio_fds[0])) 402 if (write_sigio_irq(l_write_sigio_fds[0]))
386 goto out_kill; 403 goto out_kill;
387 404
388 out: 405 /* Success, finally. */
406 memcpy(write_sigio_fds, l_write_sigio_fds, sizeof(l_write_sigio_fds));
407 memcpy(sigio_private, l_sigio_private, sizeof(l_sigio_private));
408
409 current_poll = ((struct pollfds) { .poll = p,
410 .used = 1,
411 .size = 1 });
412
389 sigio_unlock(); 413 sigio_unlock();
390 return; 414 return;
391 415
392 out_kill: 416 out_kill:
393 os_kill_process(write_sigio_pid, 1); 417 l_write_sigio_pid = write_sigio_pid;
418 write_sigio_pid = -1;
419 sigio_unlock();
420 /* Going to call waitpid, avoid holding the lock. */
421 os_kill_process(l_write_sigio_pid, 1);
422 goto out_free;
423
424 out_clear:
394 write_sigio_pid = -1; 425 write_sigio_pid = -1;
426 out_unlock:
427 sigio_unlock();
428 out_free:
429 kfree(p);
395 out_close2: 430 out_close2:
396 os_close_file(sigio_private[0]); 431 os_close_file(l_sigio_private[0]);
397 os_close_file(sigio_private[1]); 432 os_close_file(l_sigio_private[1]);
398 out_close1: 433 out_close1:
399 os_close_file(write_sigio_fds[0]); 434 os_close_file(l_write_sigio_fds[0]);
400 os_close_file(write_sigio_fds[1]); 435 os_close_file(l_write_sigio_fds[1]);
401 sigio_unlock(); 436 return;
402} 437}
403 438
404int read_sigio_fd(int fd) 439int read_sigio_fd(int fd)