spu_syscalls.c 3.7 KB

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