Commit e0168bfc by Maxime Chéramy

Merge pull request #4 from Scriptopathe/master

Scheduler decorators
parents 3f6c8497 c388d7ec
...@@ -53,6 +53,9 @@ class SchedulerInfo(object): ...@@ -53,6 +53,9 @@ class SchedulerInfo(object):
try: try:
clas = None clas = None
if self.clas: if self.clas:
if type(self.clas) is type:
clas = self.clas
else:
name = self.clas.rsplit('.', 1)[1] name = self.clas.rsplit('.', 1)[1]
importlib.import_module(self.clas) importlib.import_module(self.clas)
clas = getattr(importlib.import_module(self.clas), name) clas = getattr(importlib.import_module(self.clas), name)
......
...@@ -3,10 +3,12 @@ Implementation of the BF algorithm. ...@@ -3,10 +3,12 @@ Implementation of the BF algorithm.
Authors: Maxime Cheramy and Stefan Junker Authors: Maxime Cheramy and Stefan Junker
""" """
from simso.schedulers import scheduler
from simso.core import Scheduler, Timer from simso.core import Scheduler, Timer
from fractions import Fraction from fractions import Fraction
@scheduler("simso.schedulers.BF")
class BF(Scheduler): class BF(Scheduler):
def init(self): def init(self):
self.t_f = 0 self.t_f = 0
......
...@@ -2,8 +2,13 @@ ...@@ -2,8 +2,13 @@
Cycle-Conserving EDF. A DVFS variant of EDF (uniprocessor). Cycle-Conserving EDF. A DVFS variant of EDF (uniprocessor).
""" """
from simso.core import Scheduler from simso.core import Scheduler
from simso.schedulers import scheduler
@scheduler("simso.schedulers.CC_EDF",
required_proc_fields = [
{ 'name': 'speed', 'type': 'float', 'default': '1.0' }
]
)
class CC_EDF(Scheduler): class CC_EDF(Scheduler):
def init(self): def init(self):
self.ready_list = [] self.ready_list = []
......
...@@ -4,8 +4,9 @@ Implementation of the DP-WRAP algorithm as presented by Levin et al. in ...@@ -4,8 +4,9 @@ Implementation of the DP-WRAP algorithm as presented by Levin et al. in
""" """
from simso.core import Scheduler, Timer from simso.core import Scheduler, Timer
from math import ceil from math import ceil
from simso.schedulers import scheduler
@scheduler("simso.schedulers.DP_WRAP")
class DP_WRAP(Scheduler): class DP_WRAP(Scheduler):
def init(self): def init(self):
self.t_f = 0 self.t_f = 0
......
...@@ -4,8 +4,9 @@ __author__ = 'Pierre-Emmanuel Hladik' ...@@ -4,8 +4,9 @@ __author__ = 'Pierre-Emmanuel Hladik'
from simso.core import Scheduler from simso.core import Scheduler
from simso.schedulers import scheduler
@scheduler("simso.schedulers.EDCL")
class EDCL(Scheduler): class EDCL(Scheduler):
""" """
EDCL Scheduler. EDCL Scheduler.
......
...@@ -3,8 +3,9 @@ Implementation of the Global-EDF (Earliest Deadline First) for multiprocessor ...@@ -3,8 +3,9 @@ Implementation of the Global-EDF (Earliest Deadline First) for multiprocessor
architectures. architectures.
""" """
from simso.core import Scheduler from simso.core import Scheduler
from simso.schedulers import scheduler
@scheduler("simso.schedulers.EDF")
class EDF(Scheduler): class EDF(Scheduler):
"""Earliest Deadline First""" """Earliest Deadline First"""
def on_activate(self, job): def on_activate(self, job):
......
...@@ -3,8 +3,9 @@ Implementation of the Global-EDF (Earliest Deadline First) for multiprocessor ...@@ -3,8 +3,9 @@ Implementation of the Global-EDF (Earliest Deadline First) for multiprocessor
architectures (alternative implementation as the one provided by EDF.py). architectures (alternative implementation as the one provided by EDF.py).
""" """
from simso.core import Scheduler from simso.core import Scheduler
from simso.schedulers import scheduler
@scheduler("simso.schedulers.EDF2")
class EDF2(Scheduler): class EDF2(Scheduler):
"""Earliest Deadline First""" """Earliest Deadline First"""
def init(self): def init(self):
......
...@@ -2,8 +2,9 @@ ...@@ -2,8 +2,9 @@
Implementation of EDF-US[1/2]. Implementation of EDF-US[1/2].
""" """
from simso.core import Scheduler from simso.core import Scheduler
from simso.schedulers import scheduler
@scheduler("simso.schedulers.EDF_US")
class EDF_US(Scheduler): class EDF_US(Scheduler):
def init(self): def init(self):
self.ready_list = [] self.ready_list = []
......
...@@ -2,8 +2,9 @@ ...@@ -2,8 +2,9 @@
Earliest Deadline First algorithm for uniprocessor architectures. Earliest Deadline First algorithm for uniprocessor architectures.
""" """
from simso.core import Scheduler from simso.core import Scheduler
from simso.schedulers import scheduler
@scheduler("simso.schedulers.EDF_mono")
class EDF_mono(Scheduler): class EDF_mono(Scheduler):
def init(self): def init(self):
self.ready_list = [] self.ready_list = []
......
...@@ -8,13 +8,13 @@ from simso.core import Scheduler, Timer ...@@ -8,13 +8,13 @@ from simso.core import Scheduler, Timer
from simso.core.Scheduler import SchedulerInfo from simso.core.Scheduler import SchedulerInfo
from fractions import Fraction from fractions import Fraction
from math import ceil from math import ceil
from simso.schedulers import scheduler
migrating_tasks = {} migrating_tasks = {}
# Mapping processor to scheduler. # Mapping processor to scheduler.
map_cpu_sched = {} map_cpu_sched = {}
class EDF_modified(Scheduler): class EDF_modified(Scheduler):
""" """
An EDF mono-processor scheduler modified to accept migrating jobs. An EDF mono-processor scheduler modified to accept migrating jobs.
...@@ -69,6 +69,7 @@ class EDF_modified(Scheduler): ...@@ -69,6 +69,7 @@ class EDF_modified(Scheduler):
return (job, cpu) return (job, cpu)
@scheduler("simso.schedulers.EDHS")
class EDHS(Scheduler): class EDHS(Scheduler):
def init(self): def init(self):
# Mapping task to scheduler. # Mapping task to scheduler.
......
...@@ -2,8 +2,9 @@ ...@@ -2,8 +2,9 @@
# coding=utf-8 # coding=utf-8
from simso.core import Scheduler, Timer from simso.core import Scheduler, Timer
from simso.schedulers import scheduler
@scheduler("simso.schedulers.EDZL")
class EDZL(Scheduler): class EDZL(Scheduler):
""" """
EDZL Scheduler. EDF Scheduler with zero laxity events. EDZL Scheduler. EDF Scheduler with zero laxity events.
......
...@@ -2,6 +2,7 @@ from simso.core import Scheduler, Timer ...@@ -2,6 +2,7 @@ from simso.core import Scheduler, Timer
from simso.core.Scheduler import SchedulerInfo from simso.core.Scheduler import SchedulerInfo
from fractions import Fraction from fractions import Fraction
from math import ceil from math import ceil
from simso.schedulers import scheduler
class Modified_EDF(Scheduler): class Modified_EDF(Scheduler):
...@@ -85,7 +86,11 @@ class Group(object): ...@@ -85,7 +86,11 @@ class Group(object):
for task in self.tasks if task.jobs]) \ for task in self.tasks if task.jobs]) \
* self.sim.cycles_per_ms * self.sim.cycles_per_ms
@scheduler("simso.schedulers.EKG",
required_fields = [
{'name' : 'K', 'type' : 'int', 'default' : '0'}
]
)
class EKG(Scheduler): class EKG(Scheduler):
def init(self): def init(self):
self.groups = [] self.groups = []
......
...@@ -2,8 +2,9 @@ ...@@ -2,8 +2,9 @@
from simso.core import Scheduler, Timer from simso.core import Scheduler, Timer
from math import ceil from math import ceil
from simso.schedulers import scheduler
@scheduler("simso.schedulers.EPDF")
class EPDF(Scheduler): class EPDF(Scheduler):
"""Earliest Pseudo-Deadline First""" """Earliest Pseudo-Deadline First"""
......
...@@ -2,6 +2,7 @@ ...@@ -2,6 +2,7 @@
from simso.core import Scheduler, Timer from simso.core import Scheduler, Timer
from math import ceil from math import ceil
from simso.schedulers import scheduler
def rounded_wcet(job, q=None): def rounded_wcet(job, q=None):
...@@ -88,7 +89,7 @@ class PseudoJob(object): ...@@ -88,7 +89,7 @@ class PseudoJob(object):
return int(ceil(seq * job.deadline / rounded_wcet(job))) \ return int(ceil(seq * job.deadline / rounded_wcet(job))) \
- int((seq - 1) * job.deadline / rounded_wcet(job)) - int((seq - 1) * job.deadline / rounded_wcet(job))
@scheduler("simso.schedulers.ER_PD2")
class ER_PD2(Scheduler): class ER_PD2(Scheduler):
def init(self): def init(self):
self.ready_list = [] self.ready_list = []
......
...@@ -2,8 +2,13 @@ ...@@ -2,8 +2,13 @@
# coding=utf-8 # coding=utf-8
from simso.core import Scheduler from simso.core import Scheduler
from simso.schedulers import scheduler
@scheduler("simso.schedulers.FP",
required_task_fields = [
{'name': 'priority', 'type' : 'int', 'default' : '0' }
]
)
class FP(Scheduler): class FP(Scheduler):
""" Fixed Priority (use 'priority' field) """ """ Fixed Priority (use 'priority' field) """
def init(self): def init(self):
......
...@@ -4,8 +4,9 @@ ...@@ -4,8 +4,9 @@
from simso.core.Scheduler import SchedulerInfo from simso.core.Scheduler import SchedulerInfo
from simso.schedulers.EDF_mono import EDF_mono from simso.schedulers.EDF_mono import EDF_mono
from simso.utils import PartitionedScheduler from simso.utils import PartitionedScheduler
from simso.schedulers import scheduler
@scheduler("simso.schedulers.Fixed_PEDF")
class Fixed_PEDF(PartitionedScheduler): class Fixed_PEDF(PartitionedScheduler):
def init(self): def init(self):
PartitionedScheduler.init(self, SchedulerInfo("EDF_mono", EDF_mono)) PartitionedScheduler.init(self, SchedulerInfo("EDF_mono", EDF_mono))
......
...@@ -4,8 +4,9 @@ Anderson in Fair lateness scheduling: Reducing maximum lateness in G-EDF-like ...@@ -4,8 +4,9 @@ Anderson in Fair lateness scheduling: Reducing maximum lateness in G-EDF-like
scheduling. scheduling.
""" """
from simso.core import Scheduler from simso.core import Scheduler
from simso.schedulers import scheduler
@scheduler("simso.schedulers.G_FL")
class G_FL(Scheduler): class G_FL(Scheduler):
"""Earliest Deadline First""" """Earliest Deadline First"""
def init(self): def init(self):
......
from simso.core import Scheduler, Timer from simso.core import Scheduler, Timer
from simso.schedulers import scheduler
@scheduler("simso.schedulers.G_FL_ZL")
class G_FL_ZL(Scheduler): class G_FL_ZL(Scheduler):
""" """
G_FL with Zero Laxity Scheduler. G_FL with Zero Laxity Scheduler.
......
...@@ -5,8 +5,9 @@ Try to load balance the tasks among the processors. ...@@ -5,8 +5,9 @@ Try to load balance the tasks among the processors.
from simso.core.Scheduler import SchedulerInfo from simso.core.Scheduler import SchedulerInfo
from simso.schedulers.EDF_mono import EDF_mono from simso.schedulers.EDF_mono import EDF_mono
from simso.utils import PartitionedScheduler from simso.utils import PartitionedScheduler
from simso.schedulers import scheduler
@scheduler("simso.schedulers.LB_P_EDF")
class LB_P_EDF(PartitionedScheduler): class LB_P_EDF(PartitionedScheduler):
def init(self): def init(self):
PartitionedScheduler.init(self, SchedulerInfo("simso.schedulers.EDF_mono")) PartitionedScheduler.init(self, SchedulerInfo("simso.schedulers.EDF_mono"))
......
from simso.core import Scheduler, Timer from simso.core import Scheduler, Timer
from simso.schedulers import scheduler
@scheduler("simso.schedulers.LLF")
class LLF(Scheduler): class LLF(Scheduler):
"""Least Laxity First""" """Least Laxity First"""
def init(self): def init(self):
......
...@@ -5,8 +5,9 @@ Implementation of the LLREF scheduler as presented by Cho et al. in ...@@ -5,8 +5,9 @@ Implementation of the LLREF scheduler as presented by Cho et al. in
from simso.core import Scheduler, Timer from simso.core import Scheduler, Timer
from math import ceil from math import ceil
from simso.schedulers import scheduler
@scheduler("simso.schedulers.LLREF")
class LLREF(Scheduler): class LLREF(Scheduler):
def init(self): def init(self):
self.selected_jobs = [] # Jobs currently running. self.selected_jobs = [] # Jobs currently running.
......
...@@ -5,8 +5,9 @@ Implementation of the LLREF scheduler as presented by Cho et al. in ...@@ -5,8 +5,9 @@ Implementation of the LLREF scheduler as presented by Cho et al. in
from simso.core import Scheduler, Timer from simso.core import Scheduler, Timer
from math import ceil from math import ceil
from simso.schedulers import scheduler
@scheduler("simso.schedulers.LLREF2")
class LLREF2(Scheduler): class LLREF2(Scheduler):
def init(self): def init(self):
self.selected_jobs = [] # Jobs currently running. self.selected_jobs = [] # Jobs currently running.
......
...@@ -6,8 +6,9 @@ Optimal Multiprocessor Scheduling Algorithm for Sporadic Task Sets". ...@@ -6,8 +6,9 @@ Optimal Multiprocessor Scheduling Algorithm for Sporadic Task Sets".
from simso.core import Scheduler, Timer from simso.core import Scheduler, Timer
from heapq import heappush, heapreplace, heappop, heapify from heapq import heappush, heapreplace, heappop, heapify
from math import ceil from math import ceil
from simso.schedulers import scheduler
@scheduler("simso.schedulers.LRE_TL")
class LRE_TL(Scheduler): class LRE_TL(Scheduler):
def init(self): def init(self):
""" """
......
from simso.core import Scheduler, Timer from simso.core import Scheduler, Timer
from simso.schedulers import scheduler
@scheduler("simso.schedulers.MLLF")
class MLLF(Scheduler): class MLLF(Scheduler):
"""Modified Least Laxity First""" """Modified Least Laxity First"""
def init(self): def init(self):
......
...@@ -6,8 +6,9 @@ Multiprocessors." ...@@ -6,8 +6,9 @@ Multiprocessors."
from simso.core import Scheduler, Timer from simso.core import Scheduler, Timer
from math import ceil from math import ceil
from simso.schedulers import scheduler
@scheduler("simso.schedulers.NVNLF")
class NVNLF(Scheduler): class NVNLF(Scheduler):
def init(self): def init(self):
self.selected_jobs = [] # Jobs currently running. self.selected_jobs = [] # Jobs currently running.
......
...@@ -2,6 +2,7 @@ ...@@ -2,6 +2,7 @@
from simso.core import Scheduler, Timer from simso.core import Scheduler, Timer
from math import ceil from math import ceil
from simso.schedulers import scheduler
def rounded_wcet(job, q=None): def rounded_wcet(job, q=None):
...@@ -88,7 +89,7 @@ class PseudoJob(object): ...@@ -88,7 +89,7 @@ class PseudoJob(object):
return int(ceil(seq * job.deadline / rounded_wcet(job))) \ return int(ceil(seq * job.deadline / rounded_wcet(job))) \
- int((seq - 1) * job.deadline / rounded_wcet(job)) - int((seq - 1) * job.deadline / rounded_wcet(job))
@scheduler("simso.schedulers.PD2")
class PD2(Scheduler): class PD2(Scheduler):
quantum = 100000 # cycles quantum = 100000 # cycles
......
...@@ -4,8 +4,9 @@ Partitionned EDF using PartitionedScheduler. ...@@ -4,8 +4,9 @@ Partitionned EDF using PartitionedScheduler.
from simso.core.Scheduler import SchedulerInfo from simso.core.Scheduler import SchedulerInfo
from simso.utils import PartitionedScheduler from simso.utils import PartitionedScheduler
from simso.utils.PartitionedScheduler import decreasing_first_fit from simso.utils.PartitionedScheduler import decreasing_first_fit
from simso.schedulers import scheduler
@scheduler("simso.schedulers.P_EDF")
class P_EDF(PartitionedScheduler): class P_EDF(PartitionedScheduler):
def init(self): def init(self):
PartitionedScheduler.init( PartitionedScheduler.init(
......
...@@ -6,8 +6,9 @@ Use EDF_mono. ...@@ -6,8 +6,9 @@ Use EDF_mono.
from simso.core import Scheduler from simso.core import Scheduler
from simso.core.Scheduler import SchedulerInfo from simso.core.Scheduler import SchedulerInfo
from simso.schedulers.EDF_mono import EDF_mono from simso.schedulers.EDF_mono import EDF_mono
from simso.schedulers import scheduler
@scheduler("simso.schedulers.P_EDF2")
class P_EDF2(Scheduler): class P_EDF2(Scheduler):
def init(self): def init(self):
# Mapping processor to scheduler. # Mapping processor to scheduler.
......
...@@ -5,8 +5,9 @@ from simso.core.Scheduler import SchedulerInfo ...@@ -5,8 +5,9 @@ from simso.core.Scheduler import SchedulerInfo
from simso.schedulers.EDF_mono import EDF_mono from simso.schedulers.EDF_mono import EDF_mono
from simso.utils import PartitionedScheduler from simso.utils import PartitionedScheduler
from simso.utils.PartitionedScheduler import decreasing_worst_fit from simso.utils.PartitionedScheduler import decreasing_worst_fit
from simso.schedulers import scheduler
@scheduler("simso.schedulers.P_EDF_WF")
class P_EDF_WF(PartitionedScheduler): class P_EDF_WF(PartitionedScheduler):
def init(self): def init(self):
PartitionedScheduler.init( PartitionedScheduler.init(
......
...@@ -3,8 +3,9 @@ Partitionned EDF using PartitionedScheduler. ...@@ -3,8 +3,9 @@ Partitionned EDF using PartitionedScheduler.
""" """
from simso.core.Scheduler import SchedulerInfo from simso.core.Scheduler import SchedulerInfo
from simso.utils import PartitionedScheduler from simso.utils import PartitionedScheduler
from simso.schedulers import scheduler
@scheduler("simso.schedulers.P_RM")
class P_RM(PartitionedScheduler): class P_RM(PartitionedScheduler):
def init(self): def init(self):
PartitionedScheduler.init( PartitionedScheduler.init(
......
...@@ -4,8 +4,9 @@ Priority-Driven Scheduling of Periodic Task Systems on Multiprocessors. ...@@ -4,8 +4,9 @@ Priority-Driven Scheduling of Periodic Task Systems on Multiprocessors.
""" """
from simso.core import Scheduler from simso.core import Scheduler
from math import ceil from math import ceil
from simso.schedulers import scheduler
@scheduler("simso.schedulers.PriD")
class PriD(Scheduler): class PriD(Scheduler):
"""EDF(k) scheduler""" """EDF(k) scheduler"""
def init(self): def init(self):
......
from simso.core import Scheduler from simso.core import Scheduler
from simso.schedulers import scheduler
@scheduler("simso.schedulers.RM")
class RM(Scheduler): class RM(Scheduler):
""" Rate monotonic """ """ Rate monotonic """
def init(self): def init(self):
......
...@@ -2,8 +2,9 @@ ...@@ -2,8 +2,9 @@
Rate Monotic algorithm for uniprocessor architectures. Rate Monotic algorithm for uniprocessor architectures.
""" """
from simso.core import Scheduler from simso.core import Scheduler
from simso.schedulers import scheduler
@scheduler("simso.schedulers.RM_mono")
class RM_mono(Scheduler): class RM_mono(Scheduler):
def init(self): def init(self):
self.ready_list = [] self.ready_list = []
......
...@@ -10,8 +10,9 @@ tasks with implicit deadlines. ...@@ -10,8 +10,9 @@ tasks with implicit deadlines.
from simso.core import Scheduler, Timer from simso.core import Scheduler, Timer
from simso.schedulers.RUNServer import EDFServer, TaskServer, DualServer, \ from simso.schedulers.RUNServer import EDFServer, TaskServer, DualServer, \
select_jobs, add_job, get_child_tasks select_jobs, add_job, get_child_tasks
from simso.schedulers import scheduler
@scheduler("simso.schedulers.RUN")
class RUN(Scheduler): class RUN(Scheduler):
""" """
RUN scheduler. The offline part is done here but the online part is mainly RUN scheduler. The offline part is done here but the online part is mainly
......
...@@ -2,8 +2,13 @@ ...@@ -2,8 +2,13 @@
Static EDF. A DVFS variant of EDF (uniprocessor). Static EDF. A DVFS variant of EDF (uniprocessor).
""" """
from simso.core import Scheduler from simso.core import Scheduler
from simso.schedulers import scheduler
@scheduler("simso.schedulers.Static_EDF",
required_proc_fields = [
{ 'name': 'speed', 'type': 'float', 'default': '1.0' }
]
)
class Static_EDF(Scheduler): class Static_EDF(Scheduler):
def init(self): def init(self):
self.ready_list = [] self.ready_list = []
......
...@@ -7,8 +7,9 @@ tasks" ...@@ -7,8 +7,9 @@ tasks"
from simso.core import Scheduler, Timer from simso.core import Scheduler, Timer
from math import ceil from math import ceil
from simso.schedulers import scheduler
@scheduler("simso.schedulers.U_EDF")
class U_EDF(Scheduler): class U_EDF(Scheduler):
def init(self): def init(self):
self.al = {} self.al = {}
......
...@@ -3,8 +3,9 @@ Work-Conserving version of U-EDF. ...@@ -3,8 +3,9 @@ Work-Conserving version of U-EDF.
""" """
from simso.schedulers.RUN import RUN from simso.schedulers.RUN import RUN
from simso.schedulers import scheduler
@scheduler("simso.schedulers.WC_RUN")
class WC_RUN(RUN): class WC_RUN(RUN):
def init(self): def init(self):
RUN.init(self) RUN.init(self)
......
...@@ -3,8 +3,9 @@ Work-Conserving version of U-EDF. ...@@ -3,8 +3,9 @@ Work-Conserving version of U-EDF.
""" """
from simso.schedulers.U_EDF import U_EDF from simso.schedulers.U_EDF import U_EDF
from simso.schedulers import scheduler
@scheduler("simso.schedulers.WC_U_EDF")
class WC_U_EDF(U_EDF): class WC_U_EDF(U_EDF):
# def on_terminated(self, job): # def on_terminated(self, job):
# self.reschedule() # self.reschedule()
......
# List of all schedulers that have been declared using
# the @scheduler decorator.
__loaded_schedulers = []
# Decorator used to register a scheduler to be returned by get_declared_schedulers()
def scheduler(name, **kwargs):
"""
Decorator used to register a scheduler to be returned by get_declared_schedulers().
Mandatory arguments :
name : the complete name of the scheduler (ex : simso.schedulers.EDF)
Optional keyword arguments :
display_name : name to be shown to the user
required_fields : list of required fields for this scheduler to work correctly.
It should be a dict with the following keys :
name: name of the field
type: type of the field
default: default value of the field
required_task_fields : list of required fields for this scheduler's tasks
to work correctly. Same format as required_fields
required_proc_fields : list of required fields for this scheduler's processors
to work correctly. Same format as required_fields
The list of registered schedulers is mostly used in graphical interfaces to auto-detect
the exposed schedulers.
"""
required_fields = kwargs['required_fields'] if 'required_fields' in kwargs else []
task_f = kwargs['required_task_fields'] if 'required_task_fields' in kwargs else []
proc_f = kwargs['required_proc_fields'] if 'required_proc_fields' in kwargs else []
display_name = kwargs['display_name'] if 'display_name' in kwargs else name
def f(klass):
# Note :
# We didn't include this data into the classes because it didn't work
# properly with inheritance.
# klass.simso_name = name
# klass.simso_required_fields = required_fields
# klass.simso_required_task_fields = task_f
# klass.simso_required_proc_fields = proc_f
__loaded_schedulers.append({
'name': name,
'display_name': display_name,
'required_fields': required_fields,
'required_task_fields': task_f,
'required_proc_fields': proc_f
})
return klass
return f
def get_loaded_schedulers():
return __loaded_schedulers
\ No newline at end of file
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or sign in to comment