Skip to content
GitLab
Explore
Sign in
Register
Primary navigation
Search or go to…
Project
Miosix Kernel
Manage
Activity
Members
Labels
Plan
Issues
Issue boards
Milestones
Wiki
Code
Merge requests
Repository
Branches
Commits
Tags
Repository graph
Compare revisions
Snippets
Build
Pipelines
Jobs
Pipeline schedules
Artifacts
Deploy
Releases
Container registry
Model registry
Operate
Environments
Monitor
Incidents
Analyze
Value stream analytics
Contributor analytics
CI/CD analytics
Repository analytics
Model experiments
Help
Help
Support
GitLab documentation
Compare GitLab plans
Community forum
Contribute to GitLab
Provide feedback
Keyboard shortcuts
?
Snippets
Groups
Projects
Show more breadcrumbs
Avionics
Software Development
Miosix Kernel
Commits
269def26
Commit
269def26
authored
13 years ago
by
Terraneo Federico
Browse files
Options
Downloads
Patches
Plain Diff
Finished implementing waitpid, needs testing
parent
ad9215da
Branches
Branches containing commit
Tags
Tags containing commit
No related merge requests found
Changes
3
Show whitespace changes
Inline
Side-by-side
Showing
3 changed files
main.cpp
+5
-3
5 additions, 3 deletions
main.cpp
miosix/kernel/process.cpp
+115
-46
115 additions, 46 deletions
miosix/kernel/process.cpp
miosix/kernel/process.h
+7
-3
7 additions, 3 deletions
miosix/kernel/process.h
with
127 additions
and
52 deletions
main.cpp
+
5
−
3
View file @
269def26
...
@@ -25,12 +25,14 @@ int main()
...
@@ -25,12 +25,14 @@ int main()
Thread
::
create
(
ledThread
,
STACK_MIN
);
Thread
::
create
(
ledThread
,
STACK_MIN
);
ElfProgram
prog
(
reinterpret_cast
<
const
unsigned
int
*>
(
main_elf
),
main_elf_len
);
ElfProgram
prog
(
reinterpret_cast
<
const
unsigned
int
*>
(
main_elf
),
main_elf_len
);
for
(
;;
)
for
(
int
i
=
0
;;
i
++
)
{
{
getchar
();
getchar
();
Process
::
create
(
prog
);
pid_t
child
=
Process
::
create
(
prog
);
int
ec
;
int
ec
;
pid_t
pid
=
Process
::
wait
(
&
ec
);
pid_t
pid
;
if
(
i
%
2
==
0
)
pid
=
Process
::
wait
(
&
ec
);
else
pid
=
Process
::
waitpid
(
child
,
&
ec
,
0
);
iprintf
(
"Process %d terminated
\n
"
,
pid
);
iprintf
(
"Process %d terminated
\n
"
,
pid
);
if
(
WIFEXITED
(
ec
))
if
(
WIFEXITED
(
ec
))
{
{
...
...
This diff is collapsed.
Click to expand it.
miosix/kernel/process.cpp
+
115
−
46
View file @
269def26
...
@@ -79,8 +79,13 @@ pid_t Process::create(const ElfProgram& program)
...
@@ -79,8 +79,13 @@ pid_t Process::create(const ElfProgram& program)
Lock
<
Mutex
>
l
(
procMutex
);
Lock
<
Mutex
>
l
(
procMutex
);
proc
->
pid
=
getNewPid
();
proc
->
pid
=
getNewPid
();
if
(
Thread
::
getCurrentThread
()
->
proc
!=
0
)
if
(
Thread
::
getCurrentThread
()
->
proc
!=
0
)
{
proc
->
ppid
=
Thread
::
getCurrentThread
()
->
proc
->
pid
;
proc
->
ppid
=
Thread
::
getCurrentThread
()
->
proc
->
pid
;
else
proc
->
ppid
=
0
;
Thread
::
getCurrentThread
()
->
proc
->
childs
.
push_back
(
proc
.
get
());
}
else
{
proc
->
ppid
=
0
;
kernelChilds
.
push_back
(
proc
.
get
());
}
processes
[
proc
->
pid
]
=
proc
.
get
();
processes
[
proc
->
pid
]
=
proc
.
get
();
}
}
Thread
*
thr
=
Thread
::
createUserspace
(
Process
::
start
,
0
,
Thread
::
DEFAULT
,
Thread
*
thr
=
Thread
::
createUserspace
(
Process
::
start
,
0
,
Thread
::
DEFAULT
,
...
@@ -89,6 +94,10 @@ pid_t Process::create(const ElfProgram& program)
...
@@ -89,6 +94,10 @@ pid_t Process::create(const ElfProgram& program)
{
{
Lock
<
Mutex
>
l
(
procMutex
);
Lock
<
Mutex
>
l
(
procMutex
);
processes
.
erase
(
proc
->
pid
);
processes
.
erase
(
proc
->
pid
);
if
(
Thread
::
getCurrentThread
()
->
proc
!=
0
)
{
Thread
::
getCurrentThread
()
->
proc
->
childs
.
remove
(
proc
.
get
());
}
else
kernelChilds
.
remove
(
proc
.
get
());
throw
runtime_error
(
"Thread creation failed"
);
throw
runtime_error
(
"Thread creation failed"
);
}
}
//Cannot throw bad_alloc due to the reserve in Process's constructor.
//Cannot throw bad_alloc due to the reserve in Process's constructor.
...
@@ -113,61 +122,103 @@ pid_t Process::getppid(pid_t proc)
...
@@ -113,61 +122,103 @@ pid_t Process::getppid(pid_t proc)
pid_t
Process
::
waitpid
(
pid_t
pid
,
int
*
exit
,
int
options
)
pid_t
Process
::
waitpid
(
pid_t
pid
,
int
*
exit
,
int
options
)
{
{
Lock
<
Mutex
>
l
(
procMutex
);
Lock
<
Mutex
>
l
(
procMutex
);
pid_t
result
=-
1
;
Process
*
self
=
Thread
::
getCurrentThread
()
->
proc
;
if
(
self
==
0
)
{
//The wait is performed by the kernel
if
(
pid
<=
0
)
if
(
pid
<=
0
)
{
{
//Wait for a generic child process
//Wait for a generic child process
Process
*
self
=
Thread
::
getCurrentThread
()
->
proc
;
if
(
kernelZombies
.
empty
()
&&
(
options
&
WNOHANG
))
return
0
;
pid_t
ppid
=
self
==
0
?
0
:
self
->
pid
;
while
(
kernelZombies
.
empty
())
multimap
<
pid_t
,
Process
*>::
iterator
it
=
zombies
.
find
(
ppid
);
if
((
options
&
WNOHANG
)
&&
it
==
zombies
.
end
())
return
0
;
while
(
it
==
zombies
.
end
())
{
{
if
(
kernelChilds
.
empty
())
return
-
1
;
genericWaiting
.
wait
(
l
);
genericWaiting
.
wait
(
l
);
it
=
zombies
.
find
(
ppid
);
}
}
Process
*
joined
=
it
->
second
;
Process
*
joined
=
kernelZombies
.
front
();
kernelZombies
.
pop_front
();
processes
.
erase
(
joined
->
pid
);
if
(
joined
->
waitCount
!=
0
)
errorHandler
(
UNEXPECTED
);
if
(
joined
->
waitCount
!=
0
)
errorHandler
(
UNEXPECTED
);
result
=
joined
->
pid
;
if
(
exit
!=
0
)
*
exit
=
joined
->
exitCode
;
if
(
exit
!=
0
)
*
exit
=
joined
->
exitCode
;
zombies
.
erase
(
it
);
pid_t
result
=
joined
->
pid
;
processes
.
erase
(
result
);
delete
joined
;
delete
joined
;
return
result
;
}
else
{
}
else
{
//Wait on a specific process
//Wait on a specific
child
process
map
<
pid_t
,
Process
*>::
iterator
it
=
processes
.
find
(
pid
);
map
<
pid_t
,
Process
*>::
iterator
it
=
processes
.
find
(
pid
);
if
(
it
!=
processes
.
end
())
if
(
it
==
processes
.
end
()
||
it
->
second
->
ppid
!=
0
)
return
-
1
;
{
Process
*
joined
=
it
->
second
;
Process
*
joined
=
it
->
second
;
if
(
joined
->
exitCode
==-
1
)
if
(
joined
->
zombie
==
false
)
{
{
//Process hasn't terminated yet
//Process hasn't terminated yet
if
(
options
&
WNOHANG
)
return
0
;
if
(
options
&
WNOHANG
)
return
0
;
joined
->
waitCount
++
;
joined
->
waitCount
++
;
joined
->
waiting
.
wait
(
l
);
joined
->
waiting
.
wait
(
l
);
joined
->
waitCount
--
;
joined
->
waitCount
--
;
if
(
joined
->
waitCount
<
0
||
joined
->
exitCode
==-
1
)
if
(
joined
->
waitCount
<
0
||
joined
->
zombie
==
false
)
errorHandler
(
UNEXPECTED
);
errorHandler
(
UNEXPECTED
);
}
}
result
=
joined
->
pid
;
//If multiple threads call waitpid on the same child, the last
if
(
exit
!=
0
)
*
exit
=
joined
->
exitCode
;
//gets the return value, the other -1
pid_t
result
=-
1
;
if
(
joined
->
waitCount
==
0
)
if
(
joined
->
waitCount
==
0
)
{
{
typedef
typename
multimap
<
pid_t
,
Process
*>::
iterator
iterator
;
if
(
exit
!=
0
)
*
exit
=
joined
->
exitCode
;
pair
<
iterator
,
iterator
>
p
=
zombies
.
equal_range
(
joined
->
ppid
);
result
=
joined
->
pid
;
for
(
iterator
it
=
p
.
first
;
it
!=
p
.
second
;
++
it
)
kernelZombies
.
remove
(
joined
);
processes
.
erase
(
joined
->
pid
);
delete
joined
;
}
return
result
;
}
}
else
{
//The wait is performed by a process
if
(
pid
<=
0
)
{
//Wait for a generic child process
if
(
self
->
zombies
.
empty
()
&&
(
options
&
WNOHANG
))
return
0
;
while
(
self
->
zombies
.
empty
())
{
{
if
(
it
->
second
!=
joined
)
continue
;
if
(
self
->
childs
.
empty
())
return
-
1
;
zombies
.
erase
(
it
);
genericWaiting
.
wait
(
l
);
break
;
}
}
processes
.
erase
(
result
);
Process
*
joined
=
self
->
zombies
.
front
();
self
->
zombies
.
pop_front
();
processes
.
erase
(
joined
->
pid
);
if
(
joined
->
waitCount
!=
0
)
errorHandler
(
UNEXPECTED
);
if
(
exit
!=
0
)
*
exit
=
joined
->
exitCode
;
pid_t
result
=
joined
->
pid
;
delete
joined
;
delete
joined
;
return
result
;
}
else
{
//Wait on a specific child process
map
<
pid_t
,
Process
*>::
iterator
it
=
processes
.
find
(
pid
);
if
(
it
==
processes
.
end
()
||
it
->
second
->
ppid
!=
self
->
pid
||
pid
==
self
->
pid
)
return
-
1
;
Process
*
joined
=
it
->
second
;
if
(
joined
->
zombie
==
false
)
{
//Process hasn't terminated yet
if
(
options
&
WNOHANG
)
return
0
;
joined
->
waitCount
++
;
joined
->
waiting
.
wait
(
l
);
joined
->
waitCount
--
;
if
(
joined
->
waitCount
<
0
||
joined
->
zombie
==
false
)
errorHandler
(
UNEXPECTED
);
}
}
}
pid_t
result
=-
1
;
if
(
joined
->
waitCount
==
0
)
{
result
=
joined
->
pid
;
if
(
exit
!=
0
)
*
exit
=
joined
->
exitCode
;
self
->
zombies
.
remove
(
joined
);
processes
.
erase
(
joined
->
pid
);
delete
joined
;
}
}
return
result
;
return
result
;
}
}
}
}
Process
::~
Process
()
Process
::~
Process
()
{
{
...
@@ -177,7 +228,7 @@ Process::~Process()
...
@@ -177,7 +228,7 @@ Process::~Process()
}
}
Process
::
Process
(
const
ElfProgram
&
program
)
:
program
(
program
),
waitCount
(
0
),
Process
::
Process
(
const
ElfProgram
&
program
)
:
program
(
program
),
waitCount
(
0
),
exitCode
(
-
1
)
zombie
(
false
)
{
{
//This is required so that bad_alloc can never be thrown when the first
//This is required so that bad_alloc can never be thrown when the first
//thread of the process will be stored in this vector
//thread of the process will be stored in this vector
...
@@ -222,14 +273,13 @@ void *Process::start(void *argv)
...
@@ -222,14 +273,13 @@ void *Process::start(void *argv)
#endif //__CODE_IN_XRAM
#endif //__CODE_IN_XRAM
Thread
::
setupUserspaceContext
(
entry
,
proc
->
image
.
getProcessBasePointer
(),
Thread
::
setupUserspaceContext
(
entry
,
proc
->
image
.
getProcessBasePointer
(),
proc
->
image
.
getProcessImageSize
());
proc
->
image
.
getProcessImageSize
());
int
returnValue
=
0
;
bool
running
=
true
;
bool
running
=
true
;
do
{
do
{
miosix_private
::
SyscallParameters
sp
=
Thread
::
switchToUserspace
();
miosix_private
::
SyscallParameters
sp
=
Thread
::
switchToUserspace
();
if
(
proc
->
fault
.
faultHappened
())
if
(
proc
->
fault
.
faultHappened
())
{
{
running
=
false
;
running
=
false
;
returnValu
e
=
SIGSEGV
;
//Segfault
proc
->
exitCod
e
=
SIGSEGV
;
//Segfault
#ifdef WITH_ERRLOG
#ifdef WITH_ERRLOG
iprintf
(
"Process %d terminated due to a fault
\n
"
iprintf
(
"Process %d terminated due to a fault
\n
"
"* Code base address was 0x%x
\n
"
"* Code base address was 0x%x
\n
"
...
@@ -248,7 +298,7 @@ void *Process::start(void *argv)
...
@@ -248,7 +298,7 @@ void *Process::start(void *argv)
{
{
case
2
:
case
2
:
running
=
false
;
running
=
false
;
returnValu
e
=
(
sp
.
getFirstParameter
()
&
0xff
)
<<
8
;
proc
->
exitCod
e
=
(
sp
.
getFirstParameter
()
&
0xff
)
<<
8
;
break
;
break
;
case
3
:
case
3
:
//FIXME: check that the pointer belongs to the process
//FIXME: check that the pointer belongs to the process
...
@@ -267,7 +317,7 @@ void *Process::start(void *argv)
...
@@ -267,7 +317,7 @@ void *Process::start(void *argv)
break
;
break
;
default:
default:
running
=
false
;
running
=
false
;
returnValu
e
=
SIGSYS
;
//Bad syscall
proc
->
exitCod
e
=
SIGSYS
;
//Bad syscall
#ifdef WITH_ERRLOG
#ifdef WITH_ERRLOG
iprintf
(
"Unexpected syscall number %d
\n
"
,
sp
.
getSyscallId
());
iprintf
(
"Unexpected syscall number %d
\n
"
,
sp
.
getSyscallId
());
#endif //WITH_ERRLOG
#endif //WITH_ERRLOG
...
@@ -278,12 +328,30 @@ void *Process::start(void *argv)
...
@@ -278,12 +328,30 @@ void *Process::start(void *argv)
}
while
(
running
);
}
while
(
running
);
{
{
Lock
<
Mutex
>
l
(
procMutex
);
Lock
<
Mutex
>
l
(
procMutex
);
proc
->
exitCode
=
returnValue
;
proc
->
zombie
=
true
;
list
<
Process
*>::
iterator
it
;
for
(
it
=
proc
->
childs
.
begin
();
it
!=
proc
->
childs
.
end
();
++
it
)
(
*
it
)
->
ppid
=
0
;
for
(
it
=
proc
->
zombies
.
begin
();
it
!=
proc
->
zombies
.
end
();
++
it
)
(
*
it
)
->
ppid
=
0
;
kernelChilds
.
splice
(
kernelChilds
.
begin
(),
proc
->
childs
);
kernelZombies
.
splice
(
kernelZombies
.
begin
(),
proc
->
zombies
);
if
(
proc
->
ppid
!=
0
)
{
map
<
pid_t
,
Process
*>::
iterator
it
=
processes
.
find
(
proc
->
ppid
);
if
(
it
==
processes
.
end
())
errorHandler
(
UNEXPECTED
);
it
->
second
->
childs
.
remove
(
proc
);
if
(
proc
->
waitCount
>
0
)
proc
->
waiting
.
broadcast
();
if
(
proc
->
waitCount
>
0
)
proc
->
waiting
.
broadcast
();
else
{
else
{
zombies
.
insert
(
make_pair
(
proc
->
ppid
,
proc
)
);
it
->
second
->
zombies
.
push_back
(
proc
);
genericWaiting
.
broadcast
();
genericWaiting
.
broadcast
();
}
}
}
else
{
kernelChilds
.
remove
(
proc
);
if
(
proc
->
waitCount
>
0
)
proc
->
waiting
.
broadcast
();
else
{
kernelZombies
.
push_back
(
proc
);
genericWaiting
.
broadcast
();
}
}
}
}
return
0
;
return
0
;
}
}
...
@@ -301,7 +369,8 @@ pid_t Process::getNewPid()
...
@@ -301,7 +369,8 @@ pid_t Process::getNewPid()
}
}
map
<
pid_t
,
Process
*>
Process
::
processes
;
map
<
pid_t
,
Process
*>
Process
::
processes
;
multimap
<
pid_t
,
Process
*>
Process
::
zombies
;
std
::
list
<
Process
*>
Process
::
kernelChilds
;
std
::
list
<
Process
*>
Process
::
kernelZombies
;
pid_t
Process
::
pidCounter
=
1
;
pid_t
Process
::
pidCounter
=
1
;
Mutex
Process
::
procMutex
;
Mutex
Process
::
procMutex
;
ConditionVariable
Process
::
genericWaiting
;
ConditionVariable
Process
::
genericWaiting
;
...
...
This diff is collapsed.
Click to expand it.
miosix/kernel/process.h
+
7
−
3
View file @
269def26
...
@@ -30,6 +30,7 @@
...
@@ -30,6 +30,7 @@
#include
<vector>
#include
<vector>
#include
<map>
#include
<map>
#include
<list>
#include
<sys/types.h>
#include
<sys/types.h>
#include
"kernel.h"
#include
"kernel.h"
#include
"sync.h"
#include
"sync.h"
...
@@ -122,6 +123,8 @@ private:
...
@@ -122,6 +123,8 @@ private:
miosix_private
::
MPUConfiguration
mpu
;
///<Memory protection data
miosix_private
::
MPUConfiguration
mpu
;
///<Memory protection data
std
::
vector
<
Thread
*>
threads
;
///<Threads that belong to the process
std
::
vector
<
Thread
*>
threads
;
///<Threads that belong to the process
std
::
list
<
Process
*>
childs
;
///<Living child processes are stored here
std
::
list
<
Process
*>
zombies
;
///<Dead child processes are stored here
pid_t
pid
;
///<The pid of this process
pid_t
pid
;
///<The pid of this process
pid_t
ppid
;
///<The parent pid of this process
pid_t
ppid
;
///<The parent pid of this process
///Contains the count of active wait calls which specifically requested
///Contains the count of active wait calls which specifically requested
...
@@ -130,12 +133,13 @@ private:
...
@@ -130,12 +133,13 @@ private:
///Active wait calls which specifically requested to wait on this process
///Active wait calls which specifically requested to wait on this process
///wait on this condition variable
///wait on this condition variable
ConditionVariable
waiting
;
ConditionVariable
waiting
;
int
exitCode
;
///< Contains -1 if process is running, or the exit code
bool
zombie
;
///< True for terminated not yet joined processes
short
int
exitCode
;
///< Contains the exit code
///Maps the pid to the Process instance. Includes zombie processes
///Maps the pid to the Process instance. Includes zombie processes
static
std
::
map
<
pid_t
,
Process
*>
processes
;
static
std
::
map
<
pid_t
,
Process
*>
processes
;
///Terminated but not joined processes, the key is the parent's pid
static
std
::
list
<
Process
*>
kernelChilds
;
static
std
::
multimap
<
pid_t
,
Process
*>
z
ombies
;
static
std
::
list
<
Process
*>
kernelZ
ombies
;
///Used to assign a new pid to a process
///Used to assign a new pid to a process
static
pid_t
pidCounter
;
static
pid_t
pidCounter
;
///Uset to guard access to processes and pidCounter
///Uset to guard access to processes and pidCounter
...
...
This diff is collapsed.
Click to expand it.
Preview
0%
Loading
Try again
or
attach a new file
.
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Save comment
Cancel
Please
register
or
sign in
to comment