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
c48166bd
Commit
c48166bd
authored
13 years ago
by
Terraneo Federico
Browse files
Options
Downloads
Patches
Plain Diff
Started implementing waitpid
parent
ff09208c
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
+25
-6
25 additions, 6 deletions
main.cpp
miosix/kernel/process.cpp
+108
-8
108 additions, 8 deletions
miosix/kernel/process.cpp
miosix/kernel/process.h
+26
-23
26 additions, 23 deletions
miosix/kernel/process.h
with
159 additions
and
37 deletions
main.cpp
+
25
−
6
View file @
c48166bd
#include
<cstdio>
#include
<cstdio>
#include
<sys/wait.h>
#include
<signal.h>
#include
"miosix.h"
#include
"miosix.h"
#include
"kernel/process.h"
#include
"kernel/process.h"
#include
"app_template/prog3.h"
#include
"app_template/prog3.h"
...
@@ -7,12 +9,8 @@
...
@@ -7,12 +9,8 @@
using
namespace
std
;
using
namespace
std
;
using
namespace
miosix
;
using
namespace
miosix
;
int
main
(
)
void
ledThread
(
void
*
)
{
{
getchar
();
ElfProgram
prog
(
reinterpret_cast
<
const
unsigned
int
*>
(
main_elf
),
main_elf_len
);
Process
::
create
(
prog
);
for
(;;)
for
(;;)
{
{
ledOn
();
ledOn
();
...
@@ -21,3 +19,24 @@ int main()
...
@@ -21,3 +19,24 @@ int main()
Thread
::
sleep
(
200
);
Thread
::
sleep
(
200
);
}
}
}
}
int
main
()
{
Thread
::
create
(
ledThread
,
STACK_MIN
);
ElfProgram
prog
(
reinterpret_cast
<
const
unsigned
int
*>
(
main_elf
),
main_elf_len
);
for
(;;)
{
getchar
();
Process
::
create
(
prog
);
int
ec
;
pid_t
pid
=
Process
::
wait
(
&
ec
);
iprintf
(
"Process %d terminated
\n
"
,
pid
);
if
(
WIFEXITED
(
ec
))
{
iprintf
(
"Exit code is %d
\n
"
,
WEXITSTATUS
(
ec
));
}
else
if
(
WIFSIGNALED
(
ec
))
{
if
(
WTERMSIG
(
ec
)
==
SIGSEGV
)
iprintf
(
"Process segfaulted
\n
"
);
}
}
}
This diff is collapsed.
Click to expand it.
miosix/kernel/process.cpp
+
108
−
8
View file @
c48166bd
...
@@ -29,6 +29,8 @@
...
@@ -29,6 +29,8 @@
#include
<memory>
#include
<memory>
#include
<cstdio>
#include
<cstdio>
#include
<cstring>
#include
<cstring>
#include
<sys/wait.h>
#include
<signal.h>
#include
"sync.h"
#include
"sync.h"
#include
"process_pool.h"
#include
"process_pool.h"
#include
"process.h"
#include
"process.h"
...
@@ -70,7 +72,7 @@ namespace miosix {
...
@@ -70,7 +72,7 @@ namespace miosix {
// class Process
// class Process
//
//
Process
*
Process
::
create
(
const
ElfProgram
&
program
)
pid_t
Process
::
create
(
const
ElfProgram
&
program
)
{
{
auto_ptr
<
Process
>
proc
(
new
Process
(
program
));
auto_ptr
<
Process
>
proc
(
new
Process
(
program
));
{
{
...
@@ -95,10 +97,87 @@ Process *Process::create(const ElfProgram& program)
...
@@ -95,10 +97,87 @@ Process *Process::create(const ElfProgram& program)
//among the threads of a process
//among the threads of a process
proc
->
threads
.
push_back
(
thr
);
proc
->
threads
.
push_back
(
thr
);
thr
->
wakeup
();
//Actually start the thread, now that everything is set up
thr
->
wakeup
();
//Actually start the thread, now that everything is set up
return
proc
.
release
();
//Do not delete the pointer
pid_t
result
=
proc
->
pid
;
proc
.
release
();
//Do not delete the pointer
return
result
;
}
}
Process
::
Process
(
const
ElfProgram
&
program
)
:
program
(
program
)
pid_t
Process
::
getppid
(
pid_t
proc
)
{
Lock
<
Mutex
>
l
(
procMutex
);
map
<
pid_t
,
Process
*>::
iterator
it
=
processes
.
find
(
proc
);
if
(
it
==
processes
.
end
())
return
-
1
;
return
it
->
second
->
ppid
;
}
pid_t
Process
::
waitpid
(
pid_t
pid
,
int
*
exit
,
int
options
)
{
Lock
<
Mutex
>
l
(
procMutex
);
pid_t
result
=-
1
;
if
(
pid
<=
0
)
{
//Wait for a generic child process
Process
*
self
=
Thread
::
getCurrentThread
()
->
proc
;
pid_t
ppid
=
self
==
0
?
0
:
self
->
pid
;
multimap
<
pid_t
,
Process
*>::
iterator
it
=
zombies
.
find
(
ppid
);
if
((
options
&
WNOHANG
)
&&
it
==
zombies
.
end
())
return
0
;
while
(
it
==
zombies
.
end
())
{
genericWaiting
.
wait
(
l
);
it
=
zombies
.
find
(
ppid
);
}
Process
*
joined
=
it
->
second
;
if
(
joined
->
waitCount
!=
0
)
errorHandler
(
UNEXPECTED
);
result
=
joined
->
pid
;
if
(
exit
!=
0
)
*
exit
=
joined
->
exitCode
;
zombies
.
erase
(
it
);
processes
.
erase
(
result
);
delete
joined
;
}
else
{
//Wait on a specific process
map
<
pid_t
,
Process
*>::
iterator
it
=
processes
.
find
(
pid
);
if
(
it
!=
processes
.
end
())
{
Process
*
joined
=
it
->
second
;
if
(
joined
->
exitCode
==-
1
)
{
//Process hasn't terminated yet
if
(
options
&
WNOHANG
)
return
0
;
joined
->
waitCount
++
;
joined
->
waiting
.
wait
(
l
);
joined
->
waitCount
--
;
if
(
joined
->
waitCount
<
0
||
joined
->
exitCode
==-
1
)
errorHandler
(
UNEXPECTED
);
}
result
=
joined
->
pid
;
if
(
exit
!=
0
)
*
exit
=
joined
->
exitCode
;
if
(
joined
->
waitCount
==
0
)
{
typedef
typename
multimap
<
pid_t
,
Process
*>::
iterator
iterator
;
pair
<
iterator
,
iterator
>
p
=
zombies
.
equal_range
(
joined
->
ppid
);
for
(
iterator
it
=
p
.
first
;
it
!=
p
.
second
;
++
it
)
{
if
(
it
->
second
!=
joined
)
continue
;
zombies
.
erase
(
it
);
break
;
}
processes
.
erase
(
result
);
delete
joined
;
}
}
}
return
result
;
}
Process
::~
Process
()
{
#ifdef __CODE_IN_XRAM
ProcessPool
::
instance
().
deallocate
(
loadedProgram
);
#endif //__CODE_IN_XRAM
}
Process
::
Process
(
const
ElfProgram
&
program
)
:
program
(
program
),
waitCount
(
0
),
exitCode
(
-
1
)
{
{
//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
...
@@ -112,8 +191,18 @@ Process::Process(const ElfProgram& program) : program(program)
...
@@ -112,8 +191,18 @@ Process::Process(const ElfProgram& program) : program(program)
if
(
elfSize
<
ProcessPool
::
blockSize
)
roundedSize
=
ProcessPool
::
blockSize
;
if
(
elfSize
<
ProcessPool
::
blockSize
)
roundedSize
=
ProcessPool
::
blockSize
;
else
if
(
elfSize
&
(
elfSize
-
1
))
roundedSize
=
1
<<
ffs
(
elfSize
);
else
if
(
elfSize
&
(
elfSize
-
1
))
roundedSize
=
1
<<
ffs
(
elfSize
);
#ifndef __CODE_IN_XRAM
#ifndef __CODE_IN_XRAM
mpu
=
miosix_private
::
MPUConfiguration
(
program
.
getElfBase
(),
roundedSize
,
//FIXME -- begin
//Till a flash file system that ensures proper alignment of the programs
//loaded in flash is implemented, make the whole flash visible as a big MPU
//region
extern
unsigned
char
_end
asm
(
"_end"
);
unsigned
int
flashEnd
=
reinterpret_cast
<
unsigned
int
>
(
&
_end
);
if
(
flashEnd
&
(
flashEnd
-
1
))
flashEnd
=
1
<<
ffs
(
flashEnd
);
mpu
=
miosix_private
::
MPUConfiguration
(
0
,
flashEnd
,
image
.
getProcessBasePointer
(),
image
.
getProcessImageSize
());
image
.
getProcessBasePointer
(),
image
.
getProcessImageSize
());
// mpu=miosix_private::MPUConfiguration(program.getElfBase(),roundedSize,
// image.getProcessBasePointer(),image.getProcessImageSize());
//FIXME -- end
#else //__CODE_IN_XRAM
#else //__CODE_IN_XRAM
loadedProgram
=
ProcessPool
::
instance
().
allocate
(
roundedSize
);
loadedProgram
=
ProcessPool
::
instance
().
allocate
(
roundedSize
);
memcpy
(
loadedProgram
,
reinterpret_cast
<
char
*>
(
program
.
getElfBase
()),
elfSize
);
memcpy
(
loadedProgram
,
reinterpret_cast
<
char
*>
(
program
.
getElfBase
()),
elfSize
);
...
@@ -133,12 +222,14 @@ void *Process::start(void *argv)
...
@@ -133,12 +222,14 @@ 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
;
returnValue
=
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
"
...
@@ -157,9 +248,7 @@ void *Process::start(void *argv)
...
@@ -157,9 +248,7 @@ void *Process::start(void *argv)
{
{
case
2
:
case
2
:
running
=
false
;
running
=
false
;
#ifdef WITH_ERRLOG
returnValue
=
(
sp
.
getFirstParameter
()
&
0xff
)
<<
8
;
iprintf
(
"Exit %d
\n
"
,
sp
.
getFirstParameter
());
//FIXME: remove
#endif //WITH_ERRLOG
break
;
break
;
case
3
:
case
3
:
//FIXME: check that the pointer belongs to the process
//FIXME: check that the pointer belongs to the process
...
@@ -178,6 +267,7 @@ void *Process::start(void *argv)
...
@@ -178,6 +267,7 @@ void *Process::start(void *argv)
break
;
break
;
default:
default:
running
=
false
;
running
=
false
;
returnValue
=
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
...
@@ -186,7 +276,15 @@ void *Process::start(void *argv)
...
@@ -186,7 +276,15 @@ void *Process::start(void *argv)
}
}
if
(
Thread
::
testTerminate
())
running
=
false
;
if
(
Thread
::
testTerminate
())
running
=
false
;
}
while
(
running
);
}
while
(
running
);
//TODO: handle process termination
{
Lock
<
Mutex
>
l
(
procMutex
);
proc
->
exitCode
=
returnValue
;
if
(
proc
->
waitCount
>
0
)
proc
->
waiting
.
broadcast
();
else
{
zombies
.
insert
(
make_pair
(
proc
->
ppid
,
proc
));
genericWaiting
.
broadcast
();
}
}
return
0
;
return
0
;
}
}
...
@@ -203,8 +301,10 @@ pid_t Process::getNewPid()
...
@@ -203,8 +301,10 @@ pid_t Process::getNewPid()
}
}
map
<
pid_t
,
Process
*>
Process
::
processes
;
map
<
pid_t
,
Process
*>
Process
::
processes
;
multimap
<
pid_t
,
Process
*>
Process
::
zombies
;
pid_t
Process
::
pidCounter
=
1
;
pid_t
Process
::
pidCounter
=
1
;
Mutex
Process
::
procMutex
;
Mutex
Process
::
procMutex
;
ConditionVariable
Process
::
genericWaiting
;
}
//namespace miosix
}
//namespace miosix
...
...
This diff is collapsed.
Click to expand it.
miosix/kernel/process.h
+
26
−
23
View file @
c48166bd
...
@@ -32,6 +32,7 @@
...
@@ -32,6 +32,7 @@
#include
<map>
#include
<map>
#include
<sys/types.h>
#include
<sys/types.h>
#include
"kernel.h"
#include
"kernel.h"
#include
"sync.h"
#include
"elf_program.h"
#include
"elf_program.h"
#include
"config/miosix_settings.h"
#include
"config/miosix_settings.h"
...
@@ -48,22 +49,19 @@ public:
...
@@ -48,22 +49,19 @@ public:
/**
/**
* Create a new process
* Create a new process
* \param program Program that the process will execute
* \param program Program that the process will execute
* \return
a pointer to
the newly created process
* \return
the pid of
the newly created process
* \throws std::exception or a subclass in case of errors, including
* \throws std::exception or a subclass in case of errors, including
* not emough memory to spawn the process
* not emough memory to spawn the process
*/
*/
static
Process
*
create
(
const
ElfProgram
&
program
);
static
pid_t
create
(
const
ElfProgram
&
program
);
/**
* \return the pid of the created process
*/
pid_t
getpid
()
const
{
return
pid
;
}
/**
/**
* Given a process, returns the pid of its parent.
* \param proc the pid of a process
* \return the pid of the parent process, or zero if the process was created
* \return the pid of the parent process, or zero if the process was created
* by the kernel directly
* by the kernel directly
, or -1 if proc is not a valid process
*/
*/
pid_t
getppid
(
)
const
{
return
ppid
;
}
static
pid_t
getppid
(
pid_t
proc
);
/**
/**
* Wait for child process termination
* Wait for child process termination
...
@@ -71,7 +69,7 @@ public:
...
@@ -71,7 +69,7 @@ public:
* is not null
* is not null
* \return the pid of the terminated process, or -1 in case of errors
* \return the pid of the terminated process, or -1 in case of errors
*/
*/
pid_t
wait
(
int
*
exit
)
;
static
pid_t
wait
(
int
*
exit
)
{
return
waitpid
(
-
1
,
exit
,
0
);
}
/**
/**
* Wait for a specific child process to terminate
* Wait for a specific child process to terminate
...
@@ -83,7 +81,12 @@ public:
...
@@ -83,7 +81,12 @@ public:
* case WNOHANG is specified and the specified process has not terminated,
* case WNOHANG is specified and the specified process has not terminated,
* 0 is returned
* 0 is returned
*/
*/
pid_t
waitpid
(
pid_t
pid
,
int
*
exit
,
int
options
);
static
pid_t
waitpid
(
pid_t
pid
,
int
*
exit
,
int
options
);
/**
* Destructor
*/
~
Process
();
private
:
private
:
Process
(
const
Process
&
);
Process
(
const
Process
&
);
...
@@ -116,29 +119,29 @@ private:
...
@@ -116,29 +119,29 @@ private:
#endif //__CODE_IN_XRAM
#endif //__CODE_IN_XRAM
ProcessImage
image
;
///<The RAM image of a process
ProcessImage
image
;
///<The RAM image of a process
miosix_private
::
FaultData
fault
;
///< Contains information about faults
miosix_private
::
FaultData
fault
;
///< Contains information about faults
std
::
vector
<
Thread
*>
threads
;
///<Threads that belong to the process
miosix_private
::
MPUConfiguration
mpu
;
///<Memory protection data
miosix_private
::
MPUConfiguration
mpu
;
///<Memory protection data
std
::
vector
<
Thread
*>
threads
;
///<Threads that belong to the process
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
///This union is used to join threads. When the thread to join has not yet
///Contains the count of active wait calls which specifically requested
///terminated and no other thread called join it contains (Thread *)NULL,
///to wait on this process
///when a thread calls join on this thread it contains the thread waiting
int
waitCount
;
///for the join, and when the thread terminated it contains (void *)result
///Active wait calls which specifically requested to wait on this process
union
///wait on this condition variable
{
ConditionVariable
waiting
;
Thread
*
waitingForJoin
;
///<Thread waiting to join this
int
exitCode
;
///< Contains -1 if process is running, or the exit code
int
exitCode
;
///<Process exit code
}
joinData
;
///Maps the pid to the Process instance. Includes zombie processes
///Maps the pid to the Process instance
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
::
multimap
<
pid_t
,
Process
*>
zombies
;
///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
static
Mutex
procMutex
;
static
Mutex
procMutex
;
///Used to wait on process termination
///Used to wait on process termination
static
ConditionVariable
w
aiting
;
static
ConditionVariable
genericW
aiting
;
//Needs access to fault,mpu
//Needs access to fault,mpu
friend
class
Thread
;
friend
class
Thread
;
...
...
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