spu_syscalls.c 3.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179
  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/fs.h>
  25. #include <linux/module.h>
  26. #include <linux/syscalls.h>
  27. #include <linux/rcupdate.h>
  28. #include <linux/binfmts.h>
  29. #include <linux/syscalls.h>
  30. #include <asm/spu.h>
  31. /* protected by rcu */
  32. static struct spufs_calls *spufs_calls;
  33. #ifdef CONFIG_SPU_FS_MODULE
  34. static inline struct spufs_calls *spufs_calls_get(void)
  35. {
  36. struct spufs_calls *calls = NULL;
  37. rcu_read_lock();
  38. calls = rcu_dereference(spufs_calls);
  39. if (calls && !try_module_get(calls->owner))
  40. calls = NULL;
  41. rcu_read_unlock();
  42. return calls;
  43. }
  44. static inline void spufs_calls_put(struct spufs_calls *calls)
  45. {
  46. BUG_ON(calls != spufs_calls);
  47. /* we don't need to rcu this, as we hold a reference to the module */
  48. module_put(spufs_calls->owner);
  49. }
  50. #else /* !defined CONFIG_SPU_FS_MODULE */
  51. static inline struct spufs_calls *spufs_calls_get(void)
  52. {
  53. return spufs_calls;
  54. }
  55. static inline void spufs_calls_put(struct spufs_calls *calls) { }
  56. #endif /* CONFIG_SPU_FS_MODULE */
  57. SYSCALL_DEFINE4(spu_create, const char __user *, name, unsigned int, flags,
  58. umode_t, mode, int, neighbor_fd)
  59. {
  60. long ret;
  61. struct spufs_calls *calls;
  62. calls = spufs_calls_get();
  63. if (!calls)
  64. return -ENOSYS;
  65. if (flags & SPU_CREATE_AFFINITY_SPU) {
  66. struct fd neighbor = fdget(neighbor_fd);
  67. ret = -EBADF;
  68. if (neighbor.file) {
  69. ret = calls->create_thread(name, flags, mode, neighbor.file);
  70. fdput(neighbor);
  71. }
  72. } else
  73. ret = calls->create_thread(name, flags, mode, NULL);
  74. spufs_calls_put(calls);
  75. return ret;
  76. }
  77. SYSCALL_DEFINE3(spu_run,int, fd, __u32 __user *, unpc, __u32 __user *, ustatus)
  78. {
  79. long ret;
  80. struct fd arg;
  81. struct spufs_calls *calls;
  82. calls = spufs_calls_get();
  83. if (!calls)
  84. return -ENOSYS;
  85. ret = -EBADF;
  86. arg = fdget(fd);
  87. if (arg.file) {
  88. ret = calls->spu_run(arg.file, unpc, ustatus);
  89. fdput(arg);
  90. }
  91. spufs_calls_put(calls);
  92. return ret;
  93. }
  94. #ifdef CONFIG_COREDUMP
  95. int elf_coredump_extra_notes_size(void)
  96. {
  97. struct spufs_calls *calls;
  98. int ret;
  99. calls = spufs_calls_get();
  100. if (!calls)
  101. return 0;
  102. ret = calls->coredump_extra_notes_size();
  103. spufs_calls_put(calls);
  104. return ret;
  105. }
  106. int elf_coredump_extra_notes_write(struct coredump_params *cprm)
  107. {
  108. struct spufs_calls *calls;
  109. int ret;
  110. calls = spufs_calls_get();
  111. if (!calls)
  112. return 0;
  113. ret = calls->coredump_extra_notes_write(cprm);
  114. spufs_calls_put(calls);
  115. return ret;
  116. }
  117. #endif
  118. void notify_spus_active(void)
  119. {
  120. struct spufs_calls *calls;
  121. calls = spufs_calls_get();
  122. if (!calls)
  123. return;
  124. calls->notify_spus_active();
  125. spufs_calls_put(calls);
  126. return;
  127. }
  128. int register_spu_syscalls(struct spufs_calls *calls)
  129. {
  130. if (spufs_calls)
  131. return -EBUSY;
  132. rcu_assign_pointer(spufs_calls, calls);
  133. return 0;
  134. }
  135. EXPORT_SYMBOL_GPL(register_spu_syscalls);
  136. void unregister_spu_syscalls(struct spufs_calls *calls)
  137. {
  138. BUG_ON(spufs_calls->owner != calls->owner);
  139. RCU_INIT_POINTER(spufs_calls, NULL);
  140. synchronize_rcu();
  141. }
  142. EXPORT_SYMBOL_GPL(unregister_spu_syscalls);