spu_syscalls.c 3.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160
  1. /*
  2. * SPU file system -- system call stubs
  3. *
  4. * (C) Copyright IBM Deutschland Entwicklung GmbH 2005
  5. * (C) Copyright 2006-2007, IBM Corporation
  6. *
  7. * Author: Arnd Bergmann <arndb@de.ibm.com>
  8. *
  9. * This program is free software; you can redistribute it and/or modify
  10. * it under the terms of the GNU General Public License as published by
  11. * the Free Software Foundation; either version 2, or (at your option)
  12. * any later version.
  13. *
  14. * This program is distributed in the hope that it will be useful,
  15. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  16. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  17. * GNU General Public License for more details.
  18. *
  19. * You should have received a copy of the GNU General Public License
  20. * along with this program; if not, write to the Free Software
  21. * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  22. */
  23. #include <linux/file.h>
  24. #include <linux/module.h>
  25. #include <linux/syscalls.h>
  26. #include <linux/rcupdate.h>
  27. #include <asm/spu.h>
  28. /* protected by rcu */
  29. static struct spufs_calls *spufs_calls;
  30. #ifdef CONFIG_SPU_FS_MODULE
  31. static inline struct spufs_calls *spufs_calls_get(void)
  32. {
  33. struct spufs_calls *calls = NULL;
  34. rcu_read_lock();
  35. calls = rcu_dereference(spufs_calls);
  36. if (calls && !try_module_get(calls->owner))
  37. calls = NULL;
  38. rcu_read_unlock();
  39. return calls;
  40. }
  41. static inline void spufs_calls_put(struct spufs_calls *calls)
  42. {
  43. BUG_ON(calls != spufs_calls);
  44. /* we don't need to rcu this, as we hold a reference to the module */
  45. module_put(spufs_calls->owner);
  46. }
  47. #else /* !defined CONFIG_SPU_FS_MODULE */
  48. static inline struct spufs_calls *spufs_calls_get(void)
  49. {
  50. return spufs_calls;
  51. }
  52. static inline void spufs_calls_put(struct spufs_calls *calls) { }
  53. #endif /* CONFIG_SPU_FS_MODULE */
  54. asmlinkage long sys_spu_create(const char __user *name,
  55. unsigned int flags, mode_t mode, int neighbor_fd)
  56. {
  57. long ret;
  58. struct file *neighbor;
  59. int fput_needed;
  60. struct spufs_calls *calls;
  61. calls = spufs_calls_get();
  62. if (!calls)
  63. return -ENOSYS;
  64. if (flags & SPU_CREATE_AFFINITY_SPU) {
  65. ret = -EBADF;
  66. neighbor = fget_light(neighbor_fd, &fput_needed);
  67. if (neighbor) {
  68. ret = calls->create_thread(name, flags, mode, neighbor);
  69. fput_light(neighbor, fput_needed);
  70. }
  71. } else
  72. ret = calls->create_thread(name, flags, mode, NULL);
  73. spufs_calls_put(calls);
  74. return ret;
  75. }
  76. asmlinkage long sys_spu_run(int fd, __u32 __user *unpc, __u32 __user *ustatus)
  77. {
  78. long ret;
  79. struct file *filp;
  80. int fput_needed;
  81. struct spufs_calls *calls;
  82. calls = spufs_calls_get();
  83. if (!calls)
  84. return -ENOSYS;
  85. ret = -EBADF;
  86. filp = fget_light(fd, &fput_needed);
  87. if (filp) {
  88. ret = calls->spu_run(filp, unpc, ustatus);
  89. fput_light(filp, fput_needed);
  90. }
  91. spufs_calls_put(calls);
  92. return ret;
  93. }
  94. int arch_notes_size(void)
  95. {
  96. struct spufs_calls *calls;
  97. int ret;
  98. calls = spufs_calls_get();
  99. if (!calls)
  100. return 0;
  101. ret = calls->coredump_extra_notes_size();
  102. spufs_calls_put(calls);
  103. return ret;
  104. }
  105. void arch_write_notes(struct file *file)
  106. {
  107. struct spufs_calls *calls;
  108. calls = spufs_calls_get();
  109. if (!calls)
  110. return;
  111. calls->coredump_extra_notes_write(file);
  112. spufs_calls_put(calls);
  113. }
  114. int register_spu_syscalls(struct spufs_calls *calls)
  115. {
  116. if (spufs_calls)
  117. return -EBUSY;
  118. rcu_assign_pointer(spufs_calls, calls);
  119. return 0;
  120. }
  121. EXPORT_SYMBOL_GPL(register_spu_syscalls);
  122. void unregister_spu_syscalls(struct spufs_calls *calls)
  123. {
  124. BUG_ON(spufs_calls->owner != calls->owner);
  125. rcu_assign_pointer(spufs_calls, NULL);
  126. synchronize_rcu();
  127. }
  128. EXPORT_SYMBOL_GPL(unregister_spu_syscalls);