mirror of
https://github.com/justinian/jsix.git
synced 2025-12-10 00:14:32 -08:00
[kernel] Let objects inherit caps from superclasses
The main point of this change is to allow "global" capabilities defined on the base object type. The example here is the clone capability on all objects, which governs the ability to clone a handle. Related changes in this commit: - Renamed `kobject` to `object` as far as the syscall interface is concerned. `kobject` is the cname, but j6_cap_kobject_clone feels clunky. - The above change made me realize that the "object <type>" syntax for specifying object references was also clunky, so now it's "ref <type>" - Having to add `.object` on everywhere to access objects in interface.exposes or object.super was cumbersome, so those properties now return object types directly, instead of ObjectRef. - syscall_verify.cpp.cog now generates code to check capabilities on handles if they're specified in the definition, even when not passing an object to the implementation function.
This commit is contained in:
@@ -26,7 +26,7 @@ param: "param" name type options? description?
|
|||||||
|
|
||||||
?type: PRIMITIVE | object_name
|
?type: PRIMITIVE | object_name
|
||||||
|
|
||||||
object_name: "object" name
|
object_name: "ref" name
|
||||||
|
|
||||||
id: NUMBER
|
id: NUMBER
|
||||||
name: IDENTIFIER
|
name: IDENTIFIER
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
object channel : kobject {
|
object channel : object {
|
||||||
uid 3ea38b96aa0e54c8
|
uid 3ea38b96aa0e54c8
|
||||||
|
|
||||||
capabilities [
|
capabilities [
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
# Channels are objects that enable synchronous IPC of
|
# Channels are objects that enable synchronous IPC of
|
||||||
# arbitrary-sized messages.
|
# arbitrary-sized messages.
|
||||||
|
|
||||||
object endpoint : kobject {
|
object endpoint : object {
|
||||||
uid c5882f24a4c03b7e
|
uid c5882f24a4c03b7e
|
||||||
|
|
||||||
capabilities [
|
capabilities [
|
||||||
|
|||||||
4
definitions/objects/event.def
Normal file
4
definitions/objects/event.def
Normal file
@@ -0,0 +1,4 @@
|
|||||||
|
object event : object {
|
||||||
|
uid f441e03da5516b1a
|
||||||
|
}
|
||||||
|
|
||||||
@@ -1,5 +1,4 @@
|
|||||||
# Mailboxes are objects that enable asynchronous IPC via event notification.
|
# Mailboxes are objects that enable asynchronous IPC via event notification.
|
||||||
# This is a second line of documentation
|
|
||||||
|
|
||||||
object mailbox {
|
object mailbox {
|
||||||
uid 99934ad04ece1e07
|
uid 99934ad04ece1e07
|
||||||
@@ -11,7 +10,7 @@ object mailbox {
|
|||||||
|
|
||||||
method bind {
|
method bind {
|
||||||
param index uint
|
param index uint
|
||||||
param source object kobject
|
param source ref object
|
||||||
param event uint
|
param event uint
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,6 +1,11 @@
|
|||||||
# The base type of all kernel-exposed objects
|
# The base type of all kernel-exposed objects
|
||||||
object kobject [virtual] {
|
object object [virtual] {
|
||||||
uid 667f61fb2cd57bb4
|
uid 667f61fb2cd57bb4
|
||||||
|
cname kobject
|
||||||
|
|
||||||
|
capabilities [
|
||||||
|
clone
|
||||||
|
]
|
||||||
|
|
||||||
# Get the internal kernel object id of an object
|
# Get the internal kernel object id of an object
|
||||||
method koid {
|
method koid {
|
||||||
@@ -17,9 +22,9 @@ object kobject [virtual] {
|
|||||||
# Block the current thread waiting for an one of multiple
|
# Block the current thread waiting for an one of multiple
|
||||||
# objects to assert one of a set of signals
|
# objects to assert one of a set of signals
|
||||||
method wait_many [static] {
|
method wait_many [static] {
|
||||||
param handles object kobject [list] # The objects to wait on
|
param handles ref object [list] # The objects to wait on
|
||||||
param mask uint64 # Bitmap of which signals to wait for
|
param mask uint64 # Bitmap of which signals to wait for
|
||||||
param handle object kobject [out] # Returns the object that signalled
|
param handle ref object [out] # Returns the object that signalled
|
||||||
param signals uint64 [out] # Returns the state of the signals
|
param signals uint64 [out] # Returns the state of the signals
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1,9 +1,9 @@
|
|||||||
import "objects/kobject.def"
|
import "objects/object.def"
|
||||||
|
|
||||||
# Processes are a collection of handles and a virtual memory
|
# Processes are a collection of handles and a virtual memory
|
||||||
# space inside which threads are run.
|
# space inside which threads are run.
|
||||||
|
|
||||||
object process : kobject {
|
object process : object {
|
||||||
uid 0c69ee0b7502ba31
|
uid 0c69ee0b7502ba31
|
||||||
|
|
||||||
capabilities [
|
capabilities [
|
||||||
@@ -25,7 +25,7 @@ object process : kobject {
|
|||||||
# Give the given process a handle that points to the same
|
# Give the given process a handle that points to the same
|
||||||
# object as the specified handle.
|
# object as the specified handle.
|
||||||
method give_handle {
|
method give_handle {
|
||||||
param target object kobject [handle] # A handle in the caller process to send
|
param target ref object [handle] # A handle in the caller process to send
|
||||||
param received object kobject [out optional] # The handle as the recipient will see it
|
param received ref object [out optional] # The handle as the recipient will see it
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3,7 +3,7 @@ import "objects/vma.def"
|
|||||||
|
|
||||||
# The system object represents a handle to kernel functionality
|
# The system object represents a handle to kernel functionality
|
||||||
# needed by drivers and other priviledged services
|
# needed by drivers and other priviledged services
|
||||||
object system : kobject {
|
object system : object {
|
||||||
uid fa72506a2cf71a30
|
uid fa72506a2cf71a30
|
||||||
|
|
||||||
capabilities [
|
capabilities [
|
||||||
@@ -21,17 +21,17 @@ object system : kobject {
|
|||||||
# Ask the kernel to send this process messages whenever
|
# Ask the kernel to send this process messages whenever
|
||||||
# the given IRQ fires
|
# the given IRQ fires
|
||||||
method bind_irq [cap:bind_irq] {
|
method bind_irq [cap:bind_irq] {
|
||||||
param dest object endpoint # Endpoint that will receive messages
|
param dest ref endpoint # Endpoint that will receive messages
|
||||||
param irq uint # IRQ number to bind
|
param irq uint # IRQ number to bind
|
||||||
}
|
}
|
||||||
|
|
||||||
# Create a VMA and map an area of physical memory into it,
|
# Create a VMA and map an area of physical memory into it,
|
||||||
# also mapping that VMA into the current process
|
# also mapping that VMA into the current process
|
||||||
method map_phys [cap:map_phys] {
|
method map_phys [cap:map_phys] {
|
||||||
param area object vma [out] # Receives a handle to the VMA created
|
param area ref vma [out] # Receives a handle to the VMA created
|
||||||
param phys address # The physical address of the area
|
param phys address # The physical address of the area
|
||||||
param size size # Size of the area, in pages
|
param size size # Size of the area, in pages
|
||||||
param flags uint32 # Flags to apply to the created VMA
|
param flags uint32 # Flags to apply to the created VMA
|
||||||
}
|
}
|
||||||
|
|
||||||
# Request the kernel change the IOPL for this process. The only values
|
# Request the kernel change the IOPL for this process. The only values
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
object thread : kobject {
|
object thread : object {
|
||||||
uid 11f23e593d5761bd
|
uid 11f23e593d5761bd
|
||||||
|
|
||||||
capabilities [
|
capabilities [
|
||||||
@@ -6,7 +6,7 @@ object thread : kobject {
|
|||||||
]
|
]
|
||||||
|
|
||||||
method create [constructor] {
|
method create [constructor] {
|
||||||
param process object process [cap:create_thread]
|
param process ref process [cap:create_thread]
|
||||||
param stack_top address
|
param stack_top address
|
||||||
param entrypoint address
|
param entrypoint address
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
import "objects/process.def"
|
import "objects/process.def"
|
||||||
|
|
||||||
object vma : kobject {
|
object vma : object {
|
||||||
uid d6a12b63b3ed3937
|
uid d6a12b63b3ed3937
|
||||||
cname vm_area
|
cname vm_area
|
||||||
|
|
||||||
@@ -22,12 +22,12 @@ object vma : kobject {
|
|||||||
}
|
}
|
||||||
|
|
||||||
method map [cap:map] {
|
method map [cap:map] {
|
||||||
param process object process
|
param process ref process
|
||||||
param address address
|
param address address
|
||||||
}
|
}
|
||||||
|
|
||||||
method unmap [cap:unmap] {
|
method unmap [cap:unmap] {
|
||||||
param process object process
|
param process ref process
|
||||||
}
|
}
|
||||||
|
|
||||||
method resize [cap:resize] {
|
method resize [cap:resize] {
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
import "objects/kobject.def"
|
import "objects/object.def"
|
||||||
|
|
||||||
import "objects/channel.def"
|
import "objects/channel.def"
|
||||||
import "objects/endpoint.def"
|
import "objects/endpoint.def"
|
||||||
@@ -11,14 +11,14 @@ import "objects/vma.def"
|
|||||||
interface syscalls [syscall] {
|
interface syscalls [syscall] {
|
||||||
uid 01d9b6a948961097
|
uid 01d9b6a948961097
|
||||||
|
|
||||||
expose object system
|
expose ref object
|
||||||
expose object kobject
|
expose ref system
|
||||||
expose object event
|
expose ref event
|
||||||
expose object process
|
expose ref process
|
||||||
expose object thread
|
expose ref thread
|
||||||
expose object channel
|
expose ref channel
|
||||||
expose object endpoint
|
expose ref endpoint
|
||||||
expose object vma
|
expose ref vma
|
||||||
|
|
||||||
# Simple no-op syscall for testing
|
# Simple no-op syscall for testing
|
||||||
function noop
|
function noop
|
||||||
@@ -32,14 +32,14 @@ interface syscalls [syscall] {
|
|||||||
# supplied list is not big enough, will set the size
|
# supplied list is not big enough, will set the size
|
||||||
# needed in `size` and return j6_err_insufficient
|
# needed in `size` and return j6_err_insufficient
|
||||||
function handle_list {
|
function handle_list {
|
||||||
param handles object kobject [list inout optional] # A list of handles to be filled
|
param handles ref object [list inout optional] # A list of handles to be filled
|
||||||
}
|
}
|
||||||
|
|
||||||
# Create a clone of an existing handle, possibly with
|
# Create a clone of an existing handle, possibly with
|
||||||
# some capabilities masked out.
|
# some capabilities masked out.
|
||||||
function handle_clone {
|
function handle_clone {
|
||||||
param handle object kobject [handle] # The handle to clone
|
param orig ref object [handle cap:clone] # The handle to clone
|
||||||
param clone object kobject [out] # The new handle
|
param clone ref object [out] # The new handle
|
||||||
param mask uint32 # The capability bitmask
|
param mask uint32 # The capability bitmask
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
File diff suppressed because one or more lines are too long
@@ -18,7 +18,7 @@ class Interface:
|
|||||||
self.desc = desc
|
self.desc = desc
|
||||||
|
|
||||||
self.functions = [c for c in children if isinstance(c, Function)]
|
self.functions = [c for c in children if isinstance(c, Function)]
|
||||||
self.exposes = [e.type for e in children if isinstance(e, Expose)]
|
self.__exposes = [e.type for e in children if isinstance(e, Expose)]
|
||||||
|
|
||||||
def __str__(self):
|
def __str__(self):
|
||||||
parts = [f"interface {self.name}: {self.uid}"]
|
parts = [f"interface {self.name}: {self.uid}"]
|
||||||
@@ -35,8 +35,12 @@ class Interface:
|
|||||||
mm = [(i, None, self.functions[i]) for i in range(len(self.functions))]
|
mm = [(i, None, self.functions[i]) for i in range(len(self.functions))]
|
||||||
|
|
||||||
base = len(mm)
|
base = len(mm)
|
||||||
for o in [e.object for e in self.exposes]:
|
for o in self.exposes:
|
||||||
mm.extend([(base + i, o, o.methods[i]) for i in range(len(o.methods))])
|
mm.extend([(base + i, o, o.methods[i]) for i in range(len(o.methods))])
|
||||||
base += len(o.methods)
|
base += len(o.methods)
|
||||||
|
|
||||||
return mm
|
return mm
|
||||||
|
|
||||||
|
@property
|
||||||
|
def exposes(self):
|
||||||
|
return [ref.object for ref in self.__exposes]
|
||||||
|
|||||||
@@ -7,11 +7,12 @@ class Object:
|
|||||||
self.uid = uid
|
self.uid = uid
|
||||||
self.options = opts
|
self.options = opts
|
||||||
self.desc = desc
|
self.desc = desc
|
||||||
self.super = typename
|
|
||||||
self.methods = children
|
self.methods = children
|
||||||
self.cname = cname or name
|
self.cname = cname or name
|
||||||
self.caps = caps
|
self.caps = caps
|
||||||
|
|
||||||
|
self.__super = typename
|
||||||
|
|
||||||
from . import ObjectRef
|
from . import ObjectRef
|
||||||
self.__ref = ObjectRef(name)
|
self.__ref = ObjectRef(name)
|
||||||
|
|
||||||
@@ -25,3 +26,8 @@ class Object:
|
|||||||
return "\n".join(parts)
|
return "\n".join(parts)
|
||||||
|
|
||||||
reftype = property(lambda self: self.__ref)
|
reftype = property(lambda self: self.__ref)
|
||||||
|
|
||||||
|
@property
|
||||||
|
def super(self):
|
||||||
|
if self.__super is not None:
|
||||||
|
return self.__super.object
|
||||||
|
|||||||
@@ -17,7 +17,7 @@ ctx.parse("syscalls.def")
|
|||||||
syscalls = ctx.interfaces["syscalls"]
|
syscalls = ctx.interfaces["syscalls"]
|
||||||
|
|
||||||
for obj in syscalls.exposes:
|
for obj in syscalls.exposes:
|
||||||
cog.outl(f'#include "objects/{obj.object.cname}.h"')
|
cog.outl(f'#include "objects/{obj.cname}.h"')
|
||||||
]]]*/
|
]]]*/
|
||||||
//[[[end]]]
|
//[[[end]]]
|
||||||
|
|
||||||
@@ -51,7 +51,9 @@ for id, scope, method in syscalls.methods:
|
|||||||
argdefs = []
|
argdefs = []
|
||||||
cxxargdefs = []
|
cxxargdefs = []
|
||||||
refparams = []
|
refparams = []
|
||||||
|
|
||||||
handles = []
|
handles = []
|
||||||
|
objparams = []
|
||||||
|
|
||||||
if method.constructor:
|
if method.constructor:
|
||||||
argdefs.append("j6_handle_t *self")
|
argdefs.append("j6_handle_t *self")
|
||||||
@@ -63,11 +65,10 @@ for id, scope, method in syscalls.methods:
|
|||||||
argdefs.append("j6_handle_t self")
|
argdefs.append("j6_handle_t self")
|
||||||
cxxargdefs.append(f"obj::{scope.cname} *self")
|
cxxargdefs.append(f"obj::{scope.cname} *self")
|
||||||
args.append("self_obj")
|
args.append("self_obj")
|
||||||
handles.append((
|
|
||||||
f"obj::{scope.cname} *",
|
type = f"obj::{scope.cname} *"
|
||||||
"self",
|
handles.append((type, "self", get_caps(method.options, scope)))
|
||||||
"self_obj",
|
objparams.append((type, "self"))
|
||||||
get_caps(method.options, scope)))
|
|
||||||
|
|
||||||
for param in method.params:
|
for param in method.params:
|
||||||
needs_obj = param.type.needs_object(param.options)
|
needs_obj = param.type.needs_object(param.options)
|
||||||
@@ -81,12 +82,17 @@ for id, scope, method in syscalls.methods:
|
|||||||
cxxargdefs.append(f"{type} {arg}")
|
cxxargdefs.append(f"{type} {arg}")
|
||||||
|
|
||||||
if needs_obj:
|
if needs_obj:
|
||||||
oarg = f"{arg}_obj"
|
handles.append((type, arg, get_caps(param.options, param.type.object)))
|
||||||
handles.append((type, arg, oarg, get_caps(param.options, param.type.object)))
|
objparams.append((type, arg))
|
||||||
args.append(oarg)
|
args.append(f"{arg}_obj")
|
||||||
|
break
|
||||||
else:
|
else:
|
||||||
args.append(arg)
|
args.append(arg)
|
||||||
|
|
||||||
|
if not needs_obj and param.caps:
|
||||||
|
handles.append((
|
||||||
|
f"obj::{param.type.object.cname}",
|
||||||
|
arg, get_caps(param.options, param.type.object)))
|
||||||
|
|
||||||
if param.refparam:
|
if param.refparam:
|
||||||
subs = param.type.c_names(param.options)
|
subs = param.type.c_names(param.options)
|
||||||
@@ -103,20 +109,24 @@ for id, scope, method in syscalls.methods:
|
|||||||
cog.outl( " return j6_err_invalid_arg;")
|
cog.outl( " return j6_err_invalid_arg;")
|
||||||
cog.outl()
|
cog.outl()
|
||||||
|
|
||||||
for type, inarg, outarg, caps in handles:
|
for type, arg, caps in handles:
|
||||||
if type.endswith('*'):
|
if type.endswith('*'):
|
||||||
type = type[:-1].strip()
|
type = type[:-1].strip()
|
||||||
|
|
||||||
cog.outl(f" obj::handle *{inarg}_handle = get_handle<typename {type}>({inarg});")
|
cog.outl(f" obj::handle *{arg}_handle = get_handle<typename {type}>({arg});")
|
||||||
cog.outl(f" if (!{inarg}_handle) return j6_err_invalid_arg;")
|
cog.outl(f" if (!{arg}_handle) return j6_err_invalid_arg;")
|
||||||
|
|
||||||
if caps:
|
if caps:
|
||||||
allcaps = " | ".join(caps)
|
allcaps = " | ".join(caps)
|
||||||
cog.outl(f" j6_cap_t {inarg}_caps_req = {allcaps};")
|
cog.outl(f" j6_cap_t {arg}_caps_req = {allcaps};")
|
||||||
cog.outl(f" if (!{inarg}_handle->has_cap({inarg}_caps_req)) return j6_err_denied;")
|
cog.outl(f" if (!{arg}_handle->has_cap({arg}_caps_req)) return j6_err_denied;")
|
||||||
|
|
||||||
cog.outl(f" {type} *{outarg} = {inarg}_handle->as<typename {type}>();")
|
for type, arg in objparams:
|
||||||
cog.outl(f" if (!{outarg}) return j6_err_invalid_arg;")
|
if type.endswith('*'):
|
||||||
|
type = type[:-1].strip()
|
||||||
|
|
||||||
|
cog.outl(f" {type} *{arg}_obj = {arg}_handle->as<typename {type}>();")
|
||||||
|
cog.outl(f" if (!{arg}_obj) return j6_err_invalid_arg;")
|
||||||
cog.outl()
|
cog.outl()
|
||||||
|
|
||||||
cog.outl(f""" return {name}({", ".join(args)});""")
|
cog.outl(f""" return {name}({", ".join(args)});""")
|
||||||
|
|||||||
@@ -13,14 +13,14 @@ using namespace obj;
|
|||||||
namespace syscalls {
|
namespace syscalls {
|
||||||
|
|
||||||
j6_status_t
|
j6_status_t
|
||||||
kobject_koid(kobject *self, j6_koid_t *koid)
|
object_koid(kobject *self, j6_koid_t *koid)
|
||||||
{
|
{
|
||||||
*koid = self->koid();
|
*koid = self->koid();
|
||||||
return j6_status_ok;
|
return j6_status_ok;
|
||||||
}
|
}
|
||||||
|
|
||||||
j6_status_t
|
j6_status_t
|
||||||
kobject_wait(kobject *self, j6_signal_t mask, j6_signal_t *sigs)
|
object_wait(kobject *self, j6_signal_t mask, j6_signal_t *sigs)
|
||||||
{
|
{
|
||||||
j6_signal_t current = self->signals();
|
j6_signal_t current = self->signals();
|
||||||
if ((current & mask) != 0) {
|
if ((current & mask) != 0) {
|
||||||
@@ -40,7 +40,7 @@ kobject_wait(kobject *self, j6_signal_t mask, j6_signal_t *sigs)
|
|||||||
}
|
}
|
||||||
|
|
||||||
j6_status_t
|
j6_status_t
|
||||||
kobject_wait_many(j6_handle_t * handles, size_t handles_count, uint64_t mask, j6_handle_t * woken, uint64_t * signals)
|
object_wait_many(j6_handle_t * handles, size_t handles_count, uint64_t mask, j6_handle_t * woken, uint64_t * signals)
|
||||||
{
|
{
|
||||||
util::vector<kobject*> objects {uint32_t(handles_count)};
|
util::vector<kobject*> objects {uint32_t(handles_count)};
|
||||||
|
|
||||||
@@ -90,7 +90,7 @@ kobject_wait_many(j6_handle_t * handles, size_t handles_count, uint64_t mask, j6
|
|||||||
}
|
}
|
||||||
|
|
||||||
j6_status_t
|
j6_status_t
|
||||||
kobject_signal(kobject *self, j6_signal_t signals)
|
object_signal(kobject *self, j6_signal_t signals)
|
||||||
{
|
{
|
||||||
if ((signals & j6_signal_user_mask) != signals)
|
if ((signals & j6_signal_user_mask) != signals)
|
||||||
return j6_err_invalid_arg;
|
return j6_err_invalid_arg;
|
||||||
@@ -100,7 +100,7 @@ kobject_signal(kobject *self, j6_signal_t signals)
|
|||||||
}
|
}
|
||||||
|
|
||||||
j6_status_t
|
j6_status_t
|
||||||
kobject_close(kobject *self)
|
object_close(kobject *self)
|
||||||
{
|
{
|
||||||
self->close();
|
self->close();
|
||||||
return j6_status_ok;
|
return j6_status_ok;
|
||||||
|
|||||||
@@ -44,7 +44,7 @@ j6_status_t
|
|||||||
process_give_handle(process *self, j6_handle_t target, j6_handle_t *received)
|
process_give_handle(process *self, j6_handle_t target, j6_handle_t *received)
|
||||||
{
|
{
|
||||||
handle *target_handle = get_handle<kobject>(target);
|
handle *target_handle = get_handle<kobject>(target);
|
||||||
j6_handle_t out = self->add_handle(target_handle->object, target_handle->caps);
|
j6_handle_t out = self->add_handle(target_handle->object, target_handle->caps());
|
||||||
|
|
||||||
if (received)
|
if (received)
|
||||||
*received = out;
|
*received = out;
|
||||||
|
|||||||
@@ -13,12 +13,15 @@ syscalls = ctx.interfaces["syscalls"]
|
|||||||
|
|
||||||
for obj in syscalls.exposes:
|
for obj in syscalls.exposes:
|
||||||
i = 0
|
i = 0
|
||||||
for cap in obj.object.caps:
|
if obj.super:
|
||||||
name = f"j6_cap_{obj.object.name}_{cap}"
|
i = len(obj.super.caps)
|
||||||
|
|
||||||
|
for cap in obj.caps:
|
||||||
|
name = f"j6_cap_{obj.name}_{cap}"
|
||||||
cog.outl(f"#define {name:<30} (1 << {i})")
|
cog.outl(f"#define {name:<30} (1 << {i})")
|
||||||
i += 1
|
i += 1
|
||||||
|
|
||||||
name = f"j6_cap_{obj.object.name}_all"
|
name = f"j6_cap_{obj.name}_all"
|
||||||
cog.outl(f"#define {name:<30} ((1<<{i})-1)")
|
cog.outl(f"#define {name:<30} ((1<<{i})-1)")
|
||||||
cog.outl()
|
cog.outl()
|
||||||
]]]*/
|
]]]*/
|
||||||
|
|||||||
@@ -96,7 +96,7 @@ log_pump_proc()
|
|||||||
|
|
||||||
if (size == 0) {
|
if (size == 0) {
|
||||||
j6_signal_t sigs = 0;
|
j6_signal_t sigs = 0;
|
||||||
j6_kobject_wait(__handle_sys, j6_signal_system_has_log, &sigs);
|
j6_object_wait(__handle_sys, j6_signal_system_has_log, &sigs);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user