Skip to content
Projects
Groups
Snippets
Help
This project
Loading...
Sign in / Register
Toggle navigation
W
wine-winehq
Project
Project
Details
Activity
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Registry
Registry
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
wine
wine-winehq
Commits
57e11313
Commit
57e11313
authored
May 16, 1999
by
Alexandre Julliard
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Adapted to new select interface.
Fixed bug in *_signaled routines that could cause busy-waiting in the select loop.
parent
88de35cd
Hide whitespace changes
Inline
Side-by-side
Showing
5 changed files
with
206 additions
and
181 deletions
+206
-181
console.c
server/console.c
+59
-46
file.c
server/file.c
+57
-50
pipe.c
server/pipe.c
+38
-37
thread.c
server/thread.c
+46
-44
thread.h
server/thread.h
+6
-4
No files found.
server/console.c
View file @
57e11313
...
...
@@ -33,7 +33,7 @@ struct screen_buffer;
struct
console_input
{
struct
object
obj
;
/* object header */
int
fd
;
/* Unix file descripto
r */
struct
select_user
select
;
/* select use
r */
int
mode
;
/* input mode */
struct
screen_buffer
*
output
;
/* associated screen buffer */
int
recnum
;
/* number of input records */
...
...
@@ -43,7 +43,7 @@ struct console_input
struct
screen_buffer
{
struct
object
obj
;
/* object header */
int
fd
;
/* Unix file descripto
r */
struct
select_user
select
;
/* select use
r */
int
mode
;
/* output mode */
struct
console_input
*
input
;
/* associated console input */
int
cursor_size
;
/* size of cursor (percentage filled) */
...
...
@@ -98,11 +98,6 @@ static const struct object_ops screen_buffer_ops =
screen_buffer_destroy
};
static
const
struct
select_ops
select_ops
=
{
default_select_event
,
NULL
/* we never set a timeout on a console */
};
int
create_console
(
int
fd
,
struct
object
*
obj
[
2
]
)
{
...
...
@@ -136,19 +131,25 @@ int create_console( int fd, struct object *obj[2] )
}
init_object
(
&
console_input
->
obj
,
&
console_input_ops
,
NULL
);
init_object
(
&
screen_buffer
->
obj
,
&
screen_buffer_ops
,
NULL
);
console_input
->
fd
=
read_fd
;
console_input
->
select
.
fd
=
read_fd
;
console_input
->
select
.
func
=
default_select_event
;
console_input
->
select
.
private
=
console_input
;
console_input
->
mode
=
ENABLE_PROCESSED_INPUT
|
ENABLE_LINE_INPUT
|
ENABLE_ECHO_INPUT
|
ENABLE_MOUSE_INPUT
;
console_input
->
output
=
screen_buffer
;
console_input
->
recnum
=
0
;
console_input
->
records
=
NULL
;
screen_buffer
->
fd
=
write_fd
;
screen_buffer
->
select
.
fd
=
write_fd
;
screen_buffer
->
select
.
func
=
default_select_event
;
screen_buffer
->
select
.
private
=
screen_buffer
;
screen_buffer
->
mode
=
ENABLE_PROCESSED_OUTPUT
|
ENABLE_WRAP_AT_EOL_OUTPUT
;
screen_buffer
->
input
=
console_input
;
screen_buffer
->
cursor_size
=
100
;
screen_buffer
->
cursor_visible
=
1
;
screen_buffer
->
pid
=
0
;
screen_buffer
->
title
=
strdup
(
"Wine console"
);
register_select_user
(
&
console_input
->
select
);
register_select_user
(
&
screen_buffer
->
select
);
CLEAR_ERROR
();
obj
[
0
]
=
&
console_input
->
obj
;
obj
[
1
]
=
&
screen_buffer
->
obj
;
...
...
@@ -183,6 +184,10 @@ static int set_console_fd( int handle, int fd, int pid )
return
0
;
}
/* can't change the fd if someone is waiting on it */
assert
(
!
input
->
obj
.
head
);
assert
(
!
output
->
obj
.
head
);
if
((
fd_in
=
dup
(
fd
))
==
-
1
)
{
file_set_error
();
...
...
@@ -198,11 +203,15 @@ static int set_console_fd( int handle, int fd, int pid )
release_object
(
output
);
return
0
;
}
close
(
input
->
fd
);
close
(
output
->
fd
);
input
->
fd
=
fd_in
;
output
->
fd
=
fd_out
;
output
->
pid
=
pid
;
unregister_select_user
(
&
input
->
select
);
unregister_select_user
(
&
output
->
select
);
close
(
input
->
select
.
fd
);
close
(
output
->
select
.
fd
);
input
->
select
.
fd
=
fd_in
;
output
->
select
.
fd
=
fd_out
;
output
->
pid
=
pid
;
register_select_user
(
&
input
->
select
);
register_select_user
(
&
output
->
select
);
release_object
(
input
);
release_object
(
output
);
return
1
;
...
...
@@ -346,7 +355,7 @@ static void console_input_dump( struct object *obj, int verbose )
{
struct
console_input
*
console
=
(
struct
console_input
*
)
obj
;
assert
(
obj
->
ops
==
&
console_input_ops
);
fprintf
(
stderr
,
"Console input fd=%d
\n
"
,
console
->
fd
);
fprintf
(
stderr
,
"Console input fd=%d
\n
"
,
console
->
select
.
fd
);
}
static
int
console_input_add_queue
(
struct
object
*
obj
,
struct
wait_queue_entry
*
entry
)
...
...
@@ -354,13 +363,7 @@ static int console_input_add_queue( struct object *obj, struct wait_queue_entry
struct
console_input
*
console
=
(
struct
console_input
*
)
obj
;
assert
(
obj
->
ops
==
&
console_input_ops
);
if
(
!
obj
->
head
)
/* first on the queue */
{
if
(
!
add_select_user
(
console
->
fd
,
READ_EVENT
,
&
select_ops
,
console
))
{
SET_ERROR
(
ERROR_OUTOFMEMORY
);
return
0
;
}
}
set_select_events
(
&
console
->
select
,
READ_EVENT
);
add_queue
(
obj
,
entry
);
return
1
;
}
...
...
@@ -372,27 +375,34 @@ static void console_input_remove_queue( struct object *obj, struct wait_queue_en
remove_queue
(
obj
,
entry
);
if
(
!
obj
->
head
)
/* last on the queue is gone */
remove_select_user
(
console
->
fd
);
set_select_events
(
&
console
->
select
,
0
);
release_object
(
obj
);
}
static
int
console_input_signaled
(
struct
object
*
obj
,
struct
thread
*
thread
)
{
fd_set
fds
;
struct
timeval
tv
=
{
0
,
0
};
struct
console_input
*
console
=
(
struct
console_input
*
)
obj
;
assert
(
obj
->
ops
==
&
console_input_ops
);
FD_ZERO
(
&
fds
);
FD_SET
(
console
->
fd
,
&
fds
);
return
select
(
console
->
fd
+
1
,
&
fds
,
NULL
,
NULL
,
&
tv
)
>
0
;
if
(
check_select_events
(
&
console
->
select
,
READ_EVENT
))
{
/* stop waiting on select() if we are signaled */
set_select_events
(
&
console
->
select
,
0
);
return
1
;
}
else
{
/* restart waiting on select() if we are no longer signaled */
if
(
obj
->
head
)
set_select_events
(
&
console
->
select
,
READ_EVENT
);
return
0
;
}
}
static
int
console_input_get_read_fd
(
struct
object
*
obj
)
{
struct
console_input
*
console
=
(
struct
console_input
*
)
obj
;
assert
(
obj
->
ops
==
&
console_input_ops
);
return
dup
(
console
->
fd
);
return
dup
(
console
->
select
.
fd
);
}
static
int
console_get_info
(
struct
object
*
obj
,
struct
get_file_info_reply
*
reply
)
...
...
@@ -406,7 +416,8 @@ static void console_input_destroy( struct object *obj )
{
struct
console_input
*
console
=
(
struct
console_input
*
)
obj
;
assert
(
obj
->
ops
==
&
console_input_ops
);
close
(
console
->
fd
);
unregister_select_user
(
&
console
->
select
);
close
(
console
->
select
.
fd
);
if
(
console
->
output
)
console
->
output
->
input
=
NULL
;
free
(
console
);
}
...
...
@@ -415,7 +426,7 @@ static void screen_buffer_dump( struct object *obj, int verbose )
{
struct
screen_buffer
*
console
=
(
struct
screen_buffer
*
)
obj
;
assert
(
obj
->
ops
==
&
screen_buffer_ops
);
fprintf
(
stderr
,
"Console screen buffer fd=%d
\n
"
,
console
->
fd
);
fprintf
(
stderr
,
"Console screen buffer fd=%d
\n
"
,
console
->
select
.
fd
);
}
static
int
screen_buffer_add_queue
(
struct
object
*
obj
,
struct
wait_queue_entry
*
entry
)
...
...
@@ -423,13 +434,7 @@ static int screen_buffer_add_queue( struct object *obj, struct wait_queue_entry
struct
screen_buffer
*
console
=
(
struct
screen_buffer
*
)
obj
;
assert
(
obj
->
ops
==
&
screen_buffer_ops
);
if
(
!
obj
->
head
)
/* first on the queue */
{
if
(
!
add_select_user
(
console
->
fd
,
WRITE_EVENT
,
&
select_ops
,
console
))
{
SET_ERROR
(
ERROR_OUTOFMEMORY
);
return
0
;
}
}
set_select_events
(
&
console
->
select
,
WRITE_EVENT
);
add_queue
(
obj
,
entry
);
return
1
;
}
...
...
@@ -441,34 +446,42 @@ static void screen_buffer_remove_queue( struct object *obj, struct wait_queue_en
remove_queue
(
obj
,
entry
);
if
(
!
obj
->
head
)
/* last on the queue is gone */
remove_select_user
(
console
->
fd
);
set_select_events
(
&
console
->
select
,
0
);
release_object
(
obj
);
}
static
int
screen_buffer_signaled
(
struct
object
*
obj
,
struct
thread
*
thread
)
{
fd_set
fds
;
struct
timeval
tv
=
{
0
,
0
};
struct
screen_buffer
*
console
=
(
struct
screen_buffer
*
)
obj
;
assert
(
obj
->
ops
==
&
screen_buffer_ops
);
FD_ZERO
(
&
fds
);
FD_SET
(
console
->
fd
,
&
fds
);
return
select
(
console
->
fd
+
1
,
NULL
,
&
fds
,
NULL
,
&
tv
)
>
0
;
if
(
check_select_events
(
&
console
->
select
,
WRITE_EVENT
))
{
/* stop waiting on select() if we are signaled */
set_select_events
(
&
console
->
select
,
0
);
return
1
;
}
else
{
/* restart waiting on select() if we are no longer signaled */
if
(
obj
->
head
)
set_select_events
(
&
console
->
select
,
WRITE_EVENT
);
return
0
;
}
}
static
int
screen_buffer_get_write_fd
(
struct
object
*
obj
)
{
struct
screen_buffer
*
console
=
(
struct
screen_buffer
*
)
obj
;
assert
(
obj
->
ops
==
&
screen_buffer_ops
);
return
dup
(
console
->
fd
);
return
dup
(
console
->
select
.
fd
);
}
static
void
screen_buffer_destroy
(
struct
object
*
obj
)
{
struct
screen_buffer
*
console
=
(
struct
screen_buffer
*
)
obj
;
assert
(
obj
->
ops
==
&
screen_buffer_ops
);
close
(
console
->
fd
);
unregister_select_user
(
&
console
->
select
);
close
(
console
->
select
.
fd
);
if
(
console
->
input
)
console
->
input
->
output
=
NULL
;
if
(
console
->
pid
)
kill
(
console
->
pid
,
SIGTERM
);
if
(
console
->
title
)
free
(
console
->
title
);
...
...
server/file.c
View file @
57e11313
...
...
@@ -26,13 +26,13 @@
struct
file
{
struct
object
obj
;
/* object header */
struct
file
*
next
;
/* next file in hashing list
*/
char
*
name
;
/* file name
*/
int
fd
;
/* Unix file descriptor
*/
unsigned
int
access
;
/* file access (GENERIC_READ/WRITE) */
unsigned
int
flags
;
/* flags (FILE_FLAG_*) */
unsigned
int
sharing
;
/* file sharing mode */
struct
object
obj
;
/* object header */
struct
select_user
select
;
/* select user
*/
struct
file
*
next
;
/* next file in hashing list
*/
char
*
name
;
/* file name
*/
unsigned
int
access
;
/* file access (GENERIC_READ/WRITE) */
unsigned
int
flags
;
/* flags (FILE_FLAG_*) */
unsigned
int
sharing
;
/* file sharing mode */
};
#define NAME_HASH_SIZE 37
...
...
@@ -63,12 +63,6 @@ static const struct object_ops file_ops =
file_destroy
};
static
const
struct
select_ops
select_ops
=
{
default_select_event
,
NULL
/* we never set a timeout on a file */
};
static
int
get_name_hash
(
const
char
*
name
)
{
...
...
@@ -194,10 +188,13 @@ static struct object *create_file( int fd, const char *name, unsigned int access
file
->
next
=
NULL
;
}
init_object
(
&
file
->
obj
,
&
file_ops
,
NULL
);
file
->
fd
=
fd
;
file
->
access
=
access
;
file
->
flags
=
attrs
;
file
->
sharing
=
sharing
;
file
->
select
.
fd
=
fd
;
file
->
select
.
func
=
default_select_event
;
file
->
select
.
private
=
file
;
file
->
access
=
access
;
file
->
flags
=
attrs
;
file
->
sharing
=
sharing
;
register_select_user
(
&
file
->
select
);
CLEAR_ERROR
();
return
&
file
->
obj
;
}
...
...
@@ -231,12 +228,15 @@ struct file *create_temp_file( int access )
return
NULL
;
}
init_object
(
&
file
->
obj
,
&
file_ops
,
NULL
);
file
->
name
=
NULL
;
file
->
next
=
NULL
;
file
->
fd
=
fd
;
file
->
access
=
access
;
file
->
flags
=
0
;
file
->
sharing
=
0
;
file
->
name
=
NULL
;
file
->
next
=
NULL
;
file
->
select
.
fd
=
fd
;
file
->
select
.
func
=
default_select_event
;
file
->
select
.
private
=
file
;
file
->
access
=
access
;
file
->
flags
=
0
;
file
->
sharing
=
0
;
register_select_user
(
&
file
->
select
);
CLEAR_ERROR
();
return
file
;
}
...
...
@@ -246,7 +246,7 @@ static void file_dump( struct object *obj, int verbose )
struct
file
*
file
=
(
struct
file
*
)
obj
;
assert
(
obj
->
ops
==
&
file_ops
);
printf
(
"File fd=%d flags=%08x name='%s'
\n
"
,
file
->
fd
,
file
->
flags
,
file
->
name
);
file
->
select
.
fd
,
file
->
flags
,
file
->
name
);
}
static
int
file_add_queue
(
struct
object
*
obj
,
struct
wait_queue_entry
*
entry
)
...
...
@@ -255,11 +255,10 @@ static int file_add_queue( struct object *obj, struct wait_queue_entry *entry )
assert
(
obj
->
ops
==
&
file_ops
);
if
(
!
obj
->
head
)
/* first on the queue */
{
if
(
!
add_select_user
(
file
->
fd
,
READ_EVENT
|
WRITE_EVENT
,
&
select_ops
,
file
))
{
SET_ERROR
(
ERROR_OUTOFMEMORY
);
return
0
;
}
int
events
=
0
;
if
(
file
->
access
&
GENERIC_READ
)
events
|=
READ_EVENT
;
if
(
file
->
access
&
GENERIC_WRITE
)
events
|=
WRITE_EVENT
;
set_select_events
(
&
file
->
select
,
events
);
}
add_queue
(
obj
,
entry
);
return
1
;
...
...
@@ -272,37 +271,44 @@ static void file_remove_queue( struct object *obj, struct wait_queue_entry *entr
remove_queue
(
obj
,
entry
);
if
(
!
obj
->
head
)
/* last on the queue is gone */
remove_select_user
(
file
->
fd
);
set_select_events
(
&
file
->
select
,
0
);
release_object
(
obj
);
}
static
int
file_signaled
(
struct
object
*
obj
,
struct
thread
*
thread
)
{
fd_set
read_fds
,
write_fds
;
struct
timeval
tv
=
{
0
,
0
};
int
events
=
0
;
struct
file
*
file
=
(
struct
file
*
)
obj
;
assert
(
obj
->
ops
==
&
file_ops
);
FD_ZERO
(
&
read_fds
);
FD_ZERO
(
&
write_fds
);
if
(
file
->
access
&
GENERIC_READ
)
FD_SET
(
file
->
fd
,
&
read_fds
);
if
(
file
->
access
&
GENERIC_WRITE
)
FD_SET
(
file
->
fd
,
&
write_fds
);
return
select
(
file
->
fd
+
1
,
&
read_fds
,
&
write_fds
,
NULL
,
&
tv
)
>
0
;
if
(
file
->
access
&
GENERIC_READ
)
events
|=
READ_EVENT
;
if
(
file
->
access
&
GENERIC_WRITE
)
events
|=
WRITE_EVENT
;
if
(
check_select_events
(
&
file
->
select
,
events
))
{
/* stop waiting on select() if we are signaled */
set_select_events
(
&
file
->
select
,
0
);
return
1
;
}
else
{
/* restart waiting on select() if we are no longer signaled */
if
(
obj
->
head
)
set_select_events
(
&
file
->
select
,
events
);
return
0
;
}
}
static
int
file_get_read_fd
(
struct
object
*
obj
)
{
struct
file
*
file
=
(
struct
file
*
)
obj
;
assert
(
obj
->
ops
==
&
file_ops
);
return
dup
(
file
->
fd
);
return
dup
(
file
->
select
.
fd
);
}
static
int
file_get_write_fd
(
struct
object
*
obj
)
{
struct
file
*
file
=
(
struct
file
*
)
obj
;
assert
(
obj
->
ops
==
&
file_ops
);
return
dup
(
file
->
fd
);
return
dup
(
file
->
select
.
fd
);
}
static
int
file_flush
(
struct
object
*
obj
)
...
...
@@ -311,7 +317,7 @@ static int file_flush( struct object *obj )
struct
file
*
file
=
(
struct
file
*
)
grab_object
(
obj
);
assert
(
obj
->
ops
==
&
file_ops
);
ret
=
(
fsync
(
file
->
fd
)
!=
-
1
);
ret
=
(
fsync
(
file
->
select
.
fd
)
!=
-
1
);
if
(
!
ret
)
file_set_error
();
release_object
(
file
);
return
ret
;
...
...
@@ -323,13 +329,13 @@ static int file_get_info( struct object *obj, struct get_file_info_reply *reply
struct
file
*
file
=
(
struct
file
*
)
obj
;
assert
(
obj
->
ops
==
&
file_ops
);
if
(
fstat
(
file
->
fd
,
&
st
)
==
-
1
)
if
(
fstat
(
file
->
select
.
fd
,
&
st
)
==
-
1
)
{
file_set_error
();
return
0
;
}
if
(
S_ISCHR
(
st
.
st_mode
)
||
S_ISFIFO
(
st
.
st_mode
)
||
S_ISSOCK
(
st
.
st_mode
)
||
isatty
(
file
->
fd
))
reply
->
type
=
FILE_TYPE_CHAR
;
S_ISSOCK
(
st
.
st_mode
)
||
isatty
(
file
->
select
.
fd
))
reply
->
type
=
FILE_TYPE_CHAR
;
else
reply
->
type
=
FILE_TYPE_DISK
;
if
(
S_ISDIR
(
st
.
st_mode
))
reply
->
attr
=
FILE_ATTRIBUTE_DIRECTORY
;
else
reply
->
attr
=
FILE_ATTRIBUTE_ARCHIVE
;
...
...
@@ -360,7 +366,8 @@ static void file_destroy( struct object *obj )
if
(
file
->
flags
&
FILE_FLAG_DELETE_ON_CLOSE
)
unlink
(
file
->
name
);
free
(
file
->
name
);
}
close
(
file
->
fd
);
unregister_select_user
(
&
file
->
select
);
close
(
file
->
select
.
fd
);
free
(
file
);
}
...
...
@@ -397,7 +404,7 @@ struct file *get_file_obj( struct process *process, int handle,
int
file_get_mmap_fd
(
struct
file
*
file
)
{
return
dup
(
file
->
fd
);
return
dup
(
file
->
select
.
fd
);
}
static
int
set_file_pointer
(
int
handle
,
int
*
low
,
int
*
high
,
int
whence
)
...
...
@@ -414,7 +421,7 @@ static int set_file_pointer( int handle, int *low, int *high, int whence )
if
(
!
(
file
=
get_file_obj
(
current
->
process
,
handle
,
0
)))
return
0
;
if
((
result
=
lseek
(
file
->
fd
,
*
low
,
whence
))
==
-
1
)
if
((
result
=
lseek
(
file
->
select
.
fd
,
*
low
,
whence
))
==
-
1
)
{
/* Check for seek before start of file */
if
((
errno
==
EINVAL
)
&&
(
whence
!=
SEEK_SET
)
&&
(
*
low
<
0
))
...
...
@@ -436,8 +443,8 @@ static int truncate_file( int handle )
if
(
!
(
file
=
get_file_obj
(
current
->
process
,
handle
,
GENERIC_WRITE
)))
return
0
;
if
(((
result
=
lseek
(
file
->
fd
,
0
,
SEEK_CUR
))
==
-
1
)
||
(
ftruncate
(
file
->
fd
,
result
)
==
-
1
))
if
(((
result
=
lseek
(
file
->
select
.
fd
,
0
,
SEEK_CUR
))
==
-
1
)
||
(
ftruncate
(
file
->
select
.
fd
,
result
)
==
-
1
))
{
file_set_error
();
release_object
(
file
);
...
...
@@ -458,13 +465,13 @@ int grow_file( struct file *file, int size_high, int size_low )
SET_ERROR
(
ERROR_INVALID_PARAMETER
);
return
0
;
}
if
(
fstat
(
file
->
fd
,
&
st
)
==
-
1
)
if
(
fstat
(
file
->
select
.
fd
,
&
st
)
==
-
1
)
{
file_set_error
();
return
0
;
}
if
(
st
.
st_size
>=
size_low
)
return
1
;
/* already large enough */
if
(
ftruncate
(
file
->
fd
,
size_low
)
!=
-
1
)
return
1
;
if
(
ftruncate
(
file
->
select
.
fd
,
size_low
)
!=
-
1
)
return
1
;
file_set_error
();
return
0
;
}
...
...
server/pipe.c
View file @
57e11313
...
...
@@ -26,10 +26,10 @@ enum side { READ_SIDE, WRITE_SIDE };
struct
pipe
{
struct
object
obj
;
/* object header */
struct
pipe
*
other
;
/* the pipe other end */
int
fd
;
/* Unix file descripto
r */
enum
side
side
;
/* which side of the pipe is this */
struct
object
obj
;
/* object header */
struct
pipe
*
other
;
/* the pipe other end */
struct
select_user
select
;
/* select use
r */
enum
side
side
;
/* which side of the pipe is this */
};
static
void
pipe_dump
(
struct
object
*
obj
,
int
verbose
);
...
...
@@ -55,11 +55,6 @@ static const struct object_ops pipe_ops =
pipe_destroy
};
static
const
struct
select_ops
select_ops
=
{
default_select_event
,
NULL
/* we never set a timeout on a pipe */
};
static
int
create_pipe
(
struct
object
*
obj
[
2
]
)
{
...
...
@@ -86,14 +81,20 @@ static int create_pipe( struct object *obj[2] )
}
init_object
(
&
newpipe
[
0
]
->
obj
,
&
pipe_ops
,
NULL
);
init_object
(
&
newpipe
[
1
]
->
obj
,
&
pipe_ops
,
NULL
);
newpipe
[
0
]
->
fd
=
fd
[
0
];
newpipe
[
0
]
->
other
=
newpipe
[
1
];
newpipe
[
0
]
->
side
=
READ_SIDE
;
newpipe
[
1
]
->
fd
=
fd
[
1
];
newpipe
[
1
]
->
other
=
newpipe
[
0
];
newpipe
[
1
]
->
side
=
WRITE_SIDE
;
newpipe
[
0
]
->
select
.
fd
=
fd
[
0
];
newpipe
[
0
]
->
select
.
func
=
default_select_event
;
newpipe
[
0
]
->
select
.
private
=
newpipe
[
0
];
newpipe
[
0
]
->
other
=
newpipe
[
1
];
newpipe
[
0
]
->
side
=
READ_SIDE
;
newpipe
[
1
]
->
select
.
fd
=
fd
[
1
];
newpipe
[
1
]
->
select
.
func
=
default_select_event
;
newpipe
[
1
]
->
select
.
private
=
newpipe
[
1
];
newpipe
[
1
]
->
other
=
newpipe
[
0
];
newpipe
[
1
]
->
side
=
WRITE_SIDE
;
obj
[
0
]
=
&
newpipe
[
0
]
->
obj
;
obj
[
1
]
=
&
newpipe
[
1
]
->
obj
;
register_select_user
(
&
newpipe
[
0
]
->
select
);
register_select_user
(
&
newpipe
[
1
]
->
select
);
CLEAR_ERROR
();
return
1
;
}
...
...
@@ -103,7 +104,7 @@ static void pipe_dump( struct object *obj, int verbose )
struct
pipe
*
pipe
=
(
struct
pipe
*
)
obj
;
assert
(
obj
->
ops
==
&
pipe_ops
);
fprintf
(
stderr
,
"Pipe %s-side fd=%d
\n
"
,
(
pipe
->
side
==
READ_SIDE
)
?
"read"
:
"write"
,
pipe
->
fd
);
(
pipe
->
side
==
READ_SIDE
)
?
"read"
:
"write"
,
pipe
->
select
.
fd
);
}
static
int
pipe_add_queue
(
struct
object
*
obj
,
struct
wait_queue_entry
*
entry
)
...
...
@@ -111,15 +112,8 @@ static int pipe_add_queue( struct object *obj, struct wait_queue_entry *entry )
struct
pipe
*
pipe
=
(
struct
pipe
*
)
obj
;
assert
(
obj
->
ops
==
&
pipe_ops
);
if
(
!
obj
->
head
)
/* first on the queue */
{
if
(
!
add_select_user
(
pipe
->
fd
,
(
pipe
->
side
==
READ_SIDE
)
?
READ_EVENT
:
WRITE_EVENT
,
&
select_ops
,
pipe
))
{
SET_ERROR
(
ERROR_OUTOFMEMORY
);
return
0
;
}
}
set_select_events
(
&
pipe
->
select
,
(
pipe
->
side
==
READ_SIDE
)
?
READ_EVENT
:
WRITE_EVENT
);
add_queue
(
obj
,
entry
);
return
1
;
}
...
...
@@ -131,23 +125,29 @@ static void pipe_remove_queue( struct object *obj, struct wait_queue_entry *entr
remove_queue
(
obj
,
entry
);
if
(
!
obj
->
head
)
/* last on the queue is gone */
remove_select_user
(
pipe
->
fd
);
set_select_events
(
&
pipe
->
select
,
0
);
release_object
(
obj
);
}
static
int
pipe_signaled
(
struct
object
*
obj
,
struct
thread
*
thread
)
{
int
event
;
struct
pipe
*
pipe
=
(
struct
pipe
*
)
obj
;
struct
timeval
tv
=
{
0
,
0
};
fd_set
fds
;
assert
(
obj
->
ops
==
&
pipe_ops
);
FD_ZERO
(
&
fds
);
FD_SET
(
pipe
->
fd
,
&
fds
);
if
(
pipe
->
side
==
READ_SIDE
)
return
select
(
pipe
->
fd
+
1
,
&
fds
,
NULL
,
NULL
,
&
tv
)
>
0
;
event
=
(
pipe
->
side
==
READ_SIDE
)
?
READ_EVENT
:
WRITE_EVENT
;
if
(
check_select_events
(
&
pipe
->
select
,
event
))
{
/* stop waiting on select() if we are signaled */
set_select_events
(
&
pipe
->
select
,
0
);
return
1
;
}
else
return
select
(
pipe
->
fd
+
1
,
NULL
,
&
fds
,
NULL
,
&
tv
)
>
0
;
{
/* restart waiting on select() if we are no longer signaled */
if
(
obj
->
head
)
set_select_events
(
&
pipe
->
select
,
event
);
return
0
;
}
}
static
int
pipe_get_read_fd
(
struct
object
*
obj
)
...
...
@@ -165,7 +165,7 @@ static int pipe_get_read_fd( struct object *obj )
SET_ERROR
(
ERROR_ACCESS_DENIED
);
return
-
1
;
}
return
dup
(
pipe
->
fd
);
return
dup
(
pipe
->
select
.
fd
);
}
static
int
pipe_get_write_fd
(
struct
object
*
obj
)
...
...
@@ -183,7 +183,7 @@ static int pipe_get_write_fd( struct object *obj )
SET_ERROR
(
ERROR_ACCESS_DENIED
);
return
-
1
;
}
return
dup
(
pipe
->
fd
);
return
dup
(
pipe
->
select
.
fd
);
}
static
int
pipe_get_info
(
struct
object
*
obj
,
struct
get_file_info_reply
*
reply
)
...
...
@@ -199,7 +199,8 @@ static void pipe_destroy( struct object *obj )
assert
(
obj
->
ops
==
&
pipe_ops
);
if
(
pipe
->
other
)
pipe
->
other
->
other
=
NULL
;
close
(
pipe
->
fd
);
unregister_select_user
(
&
pipe
->
select
);
close
(
pipe
->
select
.
fd
);
free
(
pipe
);
}
...
...
server/thread.c
View file @
57e11313
...
...
@@ -40,6 +40,7 @@ struct thread_wait
int
count
;
/* count of objects */
int
flags
;
struct
timeval
timeout
;
struct
timeout_user
*
user
;
struct
wait_queue_entry
queues
[
1
];
};
...
...
@@ -80,21 +81,23 @@ static struct thread *first_thread = &initial_thread;
static
void
init_thread
(
struct
thread
*
thread
,
int
fd
)
{
init_object
(
&
thread
->
obj
,
&
thread_ops
,
NULL
);
thread
->
client_fd
=
fd
;
thread
->
unix_pid
=
0
;
/* not known yet */
thread
->
mutex
=
NULL
;
thread
->
debugger
=
NULL
;
thread
->
wait
=
NULL
;
thread
->
apc
=
NULL
;
thread
->
apc_count
=
0
;
thread
->
error
=
0
;
thread
->
state
=
STARTING
;
thread
->
exit_code
=
0x103
;
/* STILL_ACTIVE */
thread
->
next
=
NULL
;
thread
->
prev
=
NULL
;
thread
->
priority
=
THREAD_PRIORITY_NORMAL
;
thread
->
affinity
=
1
;
thread
->
suspend
=
0
;
thread
->
client
=
NULL
;
thread
->
unix_pid
=
0
;
/* not known yet */
thread
->
teb
=
NULL
;
thread
->
mutex
=
NULL
;
thread
->
debug_ctx
=
NULL
;
thread
->
debug_first
=
NULL
;
thread
->
wait
=
NULL
;
thread
->
apc
=
NULL
;
thread
->
apc_count
=
0
;
thread
->
error
=
0
;
thread
->
state
=
STARTING
;
thread
->
exit_code
=
0x103
;
/* STILL_ACTIVE */
thread
->
next
=
NULL
;
thread
->
prev
=
NULL
;
thread
->
priority
=
THREAD_PRIORITY_NORMAL
;
thread
->
affinity
=
1
;
thread
->
suspend
=
0
;
}
/* create the initial thread and start the main server loop */
...
...
@@ -104,7 +107,7 @@ void create_initial_thread( int fd )
init_thread
(
&
initial_thread
,
fd
);
initial_thread
.
process
=
create_initial_process
();
add_process_thread
(
initial_thread
.
process
,
&
initial_thread
);
add_client
(
fd
,
&
initial_thread
);
initial_thread
.
client
=
add_client
(
fd
,
&
initial_thread
);
grab_object
(
&
initial_thread
);
/* so that we never free it */
select_loop
();
}
...
...
@@ -134,7 +137,7 @@ static struct thread *create_thread( int fd, void *pid, int suspend, int inherit
if
((
*
handle
=
alloc_handle
(
current
->
process
,
thread
,
THREAD_ALL_ACCESS
,
inherit
))
==
-
1
)
goto
error
;
if
(
add_client
(
fd
,
thread
)
==
-
1
)
if
(
!
(
thread
->
client
=
add_client
(
fd
,
thread
))
)
{
SET_ERROR
(
ERROR_TOO_MANY_OPEN_FILES
);
goto
error
;
...
...
@@ -169,8 +172,8 @@ static void dump_thread( struct object *obj, int verbose )
struct
thread
*
thread
=
(
struct
thread
*
)
obj
;
assert
(
obj
->
ops
==
&
thread_ops
);
fprintf
(
stderr
,
"Thread pid=%d
fd=%d
\n
"
,
thread
->
unix_pid
,
thread
->
client_fd
);
fprintf
(
stderr
,
"Thread pid=%d
teb=%p client=%p
\n
"
,
thread
->
unix_pid
,
thread
->
teb
,
thread
->
client
);
}
static
int
thread_signaled
(
struct
object
*
obj
,
struct
thread
*
thread
)
...
...
@@ -214,7 +217,7 @@ static int suspend_thread( struct thread *thread )
int
old_count
=
thread
->
suspend
;
if
(
thread
->
suspend
<
MAXIMUM_SUSPEND_COUNT
)
{
if
(
!
thread
->
suspend
++
)
if
(
!
(
thread
->
process
->
suspend
+
thread
->
suspend
++
)
)
{
if
(
thread
->
unix_pid
)
kill
(
thread
->
unix_pid
,
SIGSTOP
);
}
...
...
@@ -228,7 +231,7 @@ static int resume_thread( struct thread *thread )
int
old_count
=
thread
->
suspend
;
if
(
thread
->
suspend
>
0
)
{
if
(
!
--
thread
->
suspend
)
if
(
!
(
--
thread
->
suspend
+
thread
->
process
->
suspend
)
)
{
if
(
thread
->
unix_pid
)
kill
(
thread
->
unix_pid
,
SIGCONT
);
}
...
...
@@ -270,7 +273,7 @@ int send_reply( struct thread *thread, int pass_fd, int n,
vec
[
i
].
iov_len
=
va_arg
(
args
,
int
);
}
va_end
(
args
);
return
send_reply_v
(
thread
->
client
_fd
,
thread
->
error
,
pass_fd
,
vec
,
n
);
return
send_reply_v
(
thread
->
client
,
thread
->
error
,
pass_fd
,
vec
,
n
);
}
/* add a thread to an object wait queue; return 1 if OK, 0 on error */
...
...
@@ -306,7 +309,7 @@ static void end_wait( struct thread *thread )
assert
(
wait
);
for
(
i
=
0
,
entry
=
wait
->
queues
;
i
<
wait
->
count
;
i
++
,
entry
++
)
entry
->
obj
->
ops
->
remove_queue
(
entry
->
obj
,
entry
);
if
(
wait
->
flags
&
SELECT_TIMEOUT
)
set_select_timeout
(
thread
->
client_fd
,
NULL
);
if
(
wait
->
user
)
remove_timeout_user
(
wait
->
user
);
free
(
wait
);
thread
->
wait
=
NULL
;
}
...
...
@@ -329,20 +332,8 @@ static int wait_on( struct thread *thread, int count,
thread
->
wait
=
wait
;
wait
->
count
=
count
;
wait
->
flags
=
flags
;
if
(
flags
&
SELECT_TIMEOUT
)
{
gettimeofday
(
&
wait
->
timeout
,
0
);
if
(
timeout
)
{
wait
->
timeout
.
tv_usec
+=
(
timeout
%
1000
)
*
1000
;
if
(
wait
->
timeout
.
tv_usec
>=
1000000
)
{
wait
->
timeout
.
tv_usec
-=
1000000
;
wait
->
timeout
.
tv_sec
++
;
}
wait
->
timeout
.
tv_sec
+=
timeout
/
1000
;
}
}
wait
->
user
=
NULL
;
if
(
flags
&
SELECT_TIMEOUT
)
make_timeout
(
&
wait
->
timeout
,
timeout
);
for
(
i
=
0
,
entry
=
wait
->
queues
;
i
<
count
;
i
++
,
entry
++
)
{
...
...
@@ -375,8 +366,12 @@ static int check_wait( struct thread *thread, int *signaled )
assert
(
wait
);
if
(
wait
->
flags
&
SELECT_ALL
)
{
int
not_ok
=
0
;
/* Note: we must check them all anyway, as some objects may
* want to do something when signaled, even if others are not */
for
(
i
=
0
,
entry
=
wait
->
queues
;
i
<
wait
->
count
;
i
++
,
entry
++
)
if
(
!
entry
->
obj
->
ops
->
signaled
(
entry
->
obj
,
thread
))
goto
other_checks
;
not_ok
|=
!
entry
->
obj
->
ops
->
signaled
(
entry
->
obj
,
thread
);
if
(
not_ok
)
goto
other_checks
;
/* Wait satisfied: tell it to all objects */
*
signaled
=
0
;
for
(
i
=
0
,
entry
=
wait
->
queues
;
i
<
wait
->
count
;
i
++
,
entry
++
)
...
...
@@ -458,11 +453,15 @@ static void sleep_on( struct thread *thread, int count, int *handles, int flags,
send_select_reply
(
thread
,
-
1
);
return
;
}
if
(
!
wake_thread
(
thread
))
if
(
wake_thread
(
thread
))
return
;
/* now we need to wait */
if
(
flags
&
SELECT_TIMEOUT
)
{
/* we need to wait */
if
(
flags
&
SELECT_TIMEOUT
)
set_select_timeout
(
thread
->
client_fd
,
&
thread
->
wait
->
timeout
);
if
(
!
(
thread
->
wait
->
user
=
add_timeout_user
(
&
thread
->
wait
->
timeout
,
call_timeout_handler
,
thread
)))
{
send_select_reply
(
thread
,
-
1
);
}
}
}
...
...
@@ -470,6 +469,7 @@ static void sleep_on( struct thread *thread, int count, int *handles, int flags,
void
thread_timeout
(
void
)
{
assert
(
current
->
wait
);
current
->
wait
->
user
=
NULL
;
end_wait
(
current
);
send_select_reply
(
current
,
STATUS_TIMEOUT
);
}
...
...
@@ -513,7 +513,7 @@ void kill_thread( struct thread *thread, int exit_code )
{
if
(
thread
->
state
==
TERMINATED
)
return
;
/* already killed */
if
(
thread
->
unix_pid
)
kill
(
thread
->
unix_pid
,
SIGTERM
);
remove_client
(
thread
->
client
_fd
,
exit_code
);
/* this will call thread_killed */
remove_client
(
thread
->
client
,
exit_code
);
/* this will call thread_killed */
}
/* a thread has been killed */
...
...
@@ -558,7 +558,9 @@ DECL_HANDLER(init_thread)
}
current
->
state
=
RUNNING
;
current
->
unix_pid
=
req
->
unix_pid
;
if
(
current
->
suspend
>
0
)
kill
(
current
->
unix_pid
,
SIGSTOP
);
current
->
teb
=
req
->
teb
;
if
(
current
->
suspend
+
current
->
process
->
suspend
>
0
)
kill
(
current
->
unix_pid
,
SIGSTOP
);
reply
.
pid
=
current
->
process
;
reply
.
tid
=
current
;
send_reply
(
current
,
-
1
,
1
,
&
reply
,
sizeof
(
reply
)
);
...
...
server/thread.h
View file @
57e11313
...
...
@@ -19,7 +19,7 @@ struct process;
struct
thread_wait
;
struct
thread_apc
;
struct
mutex
;
struct
debug
ger
;
struct
debug
_ctx
;
enum
run_state
{
STARTING
,
RUNNING
,
TERMINATED
};
...
...
@@ -31,16 +31,18 @@ struct thread
struct
thread
*
proc_next
;
/* per-process thread list */
struct
thread
*
proc_prev
;
struct
process
*
process
;
struct
mutex
*
mutex
;
/* list of currently owned mutexes */
struct
debugger
*
debugger
;
/* debugger info if this thread is a debugger */
struct
mutex
*
mutex
;
/* list of currently owned mutexes */
struct
debug_ctx
*
debug_ctx
;
/* debugger context if this thread is a debugger */
struct
process
*
debug_first
;
/* head of debugged processes list */
struct
thread_wait
*
wait
;
/* current wait condition if sleeping */
struct
thread_apc
*
apc
;
/* list of async procedure calls */
int
apc_count
;
/* number of outstanding APCs */
int
error
;
/* current error code */
enum
run_state
state
;
/* running state */
int
exit_code
;
/* thread exit code */
int
client_fd
;
/* client fd
for socket communications */
struct
client
*
client
;
/* client
for socket communications */
int
unix_pid
;
/* Unix pid of client */
void
*
teb
;
/* TEB address (in client address space) */
int
priority
;
/* priority level */
int
affinity
;
/* affinity mask */
int
suspend
;
/* suspend count */
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment