
\section{kobjects and subsystems}

The kobject infrastructure was developed to consolidate common aspects
of driver model objects. The result is a simple object type designed
to provide a foundation for more complex object types. Struct
subsystem was created to describe and manage sets of kobjects. It was
also created to consolidate and unify driver model objects and
functions. 


\subsection*{kobjects}

Struct kobject provides basic object attributes in a structure that is
designed to be embedded in larger structures. Subsystems that embed
kobject may use its members, and the helpers for them, rather than
defining their own. 

\begin{table}
\begin{footnotesize}
\begin{tabularx}{\linewidth}{|X|X|X|} \hline
\textit{Name}	& \textit{Type} & \textit{Description} \\ \hline \hline

name	&  char [KOBJ\_NAME\_LEN] & Name of object. \\ \hline

refcount	& atomic\_t	& Reference count of kobject. \\ \hline

entry
& struct list\_head
& List entry in subsystem's list of objects.
\\\hline 

parent	& struct kobject *	& Parent object. \\ \hline
subsys	& struct subsystem *	& kobject's subsystem. \\ \hline
dentry	& struct dentry *	& Dentry of object's sysfs directory. \\ \hline

\end{tabularx}
\end{footnotesize}
\caption{\footnotesize{struct kobject data fields}}
\end{table}

When a kobject is registered, it should initialize the following
fields: 

\begin{itemize}
\item name
\item parent
\item subsys
\end{itemize}

'name' gives the object identity, and provides a name for its sysfs
directory that is created. 'parent' provides ancestral context for the
object. The kobject infrastructure inserts the kobject into an ordered
list that resides in its subsystem. The ordering is dependent on the
kobject's parent - the object is inserted directly before its
parent. This ordering guarantees a depth-first ordering when iterating
over the list forwards, and a breadth first ordering when iterating
over it backwards. 

The 'subsys' informs the kobject core of the kobject's controlling
subsystem. A kobject may belong to only one subsystem at a 
time. 
Note that a kobject's parent is set to point to its subsystem, if its
parent pointer is not set by the kobject core. 


\subsection*{kobject Programming Interface}

\begin{table}
\begin{footnotesize}
\begin{tabularx}{\linewidth}{|X|X|X|} \hline

\textit{Name} 
& \textit{Return Type} 
& \textit{Description}
\\ \hline \hline

kobject\_init( 
struct kobject *
)  &
void & 
Initialize kobject only. \\ \hline

kobject\_cleanup(
  struct kobject *
) &
void &
Tear down kobject, by calling its subsystem's release() method. Used
internally only. \\ \hline

kobject\_add(
  struct kobject *
) &
int & 
Add kobject to object hierarchy. \\ \hline

kobject\_del(
  struct kobject *
) &
void & 
Remove kobject from object hierarchy. \\ \hline

kobject\_register(
  struct kobject *
) &
int & 
Initialize kobject AND add to object hierarchy. \\ \hline

kobject\_unregister(
  struct kobject *
) &
void &
Remove kobject from object hierarchy and decrement reference count. \\ \hline 

kobject\_get(
  struct kobject *
) &
struct kobject * &
Increment reference count of kobject. \\ \hline

kobject\_put(
  struct kobject *
) &
void &
Decrement reference count of kobject, and tear it down if the count
reaches 0. \\ \hline

\end{tabularx}
\end{footnotesize}
\caption{\footnotesize{kobject Programming Interface}}
\end{table}

Kobjects may be dynamically added and removed from their
subsystem. The kobject programming interface provides two
parallel programming models, much like devices do. kobject\_register()
initializes the kobject, and adds to the kobject 
hierarchy. The same action may also be performed by calling
kobject\_init() and kobject\_add() manually. 

kobject\_unregister() removes the kobject from the system and
decrements its reference count. When the reference count of the
kobject reaches 0, kobject\_cleanup() will be called to tear down the
kobject. Alternatively, one may call kobject\_del() and kobject\_put()
to obtain the same results. kobject\_cleanup() is called only by
kobject\_put(), and should never be called manually. 

The parallel interface is provided to afford users of the kobject
model more flexibility. kobject\_add() inserts the kobject into its
subsystem and creates a sysfs directory for it. A user may not desire
that to happen immediately, or at all. kobject\_init() may be called
to initialize the kobject to a state in which the reference count is
usable. At a later time, the user may call kobject\_add() add the
device to the subsystem and create its sysfs directory. 


Users of the low-level initialize and add calls should also use the
low-level kobject\_del() and kobject\_put() calls, even if they happen
consecutively, like kobject\_unregister(). Even though
kobject\_register() and kobject\_unregister() currently do no extra
work, they are not excluded from ever doing so. Adhering to the
symmetry also makes the code easier to follow and understand.


A kobject contains a reference count that should be incremented --
using kobject\_get() -- before accessing it, and decremented - using
kobject\_put() -- after it's not being used any more. Keeping a
positive reference count on an object guarantees that the structure
will not be removed and freed while it's being used. 



\subsection*{Subsystems}

struct subsystem was defined to describe a collection of kobjects.
'subsystem' is an ambiguous name for such a generic object;
'container' is more accurate, and will likely change at a later
date. The object contains members to manage its set of subordinate
kobjects. Users of subsystem objects may embed the structure in more
complex objects and use the fields contained in it, rather than
defining their own.


\begin{table}
\begin{footnotesize}
\begin{tabularx}{\linewidth}{|X|X|X|} \hline
\textit{Name}	& \textit{Type} & \textit{Description} \\ \hline \hline

kobj	& struct kobject	& Generic object metadata. \\\hline
list	& struct list\_head	& List of registered objects. \\\hline
rwsem	& struct rw\_semaphore	& Read/write semaphore for subsystem. \\\hline
parent	& struct subsystem *	& Parent subsystem. \\\hline
sysfs\_ops	& struct sysfs\_ops *	& 
	Operations for reading and writing subordinate kobject
	attributes via sysfs. \\\hline 
default\_attrs	& struct attribute **	& NULL-terminated array of
	attributes exported via sysfs for every kobject registered with
	subsystem. \\\hline

\end{tabularx} 
\end{footnotesize}
\caption{\footnotesize{struct subsystem data fields}}
\end{table}

\begin{table}
\begin{footnotesize}
\begin{tabularx}{\linewidth}{|X|X|X|} \hline
\textit{Name}	& \textit{Return Type} & \textit{Description} \\ \hline \hline
release(
  struct device * 
)	& void	& 
	Method called when a registered kobject's reference count
	reaches 0. Used by the subsystem to free memory allocated for
	kobject. \\\hline

\end{tabularx} 
\end{footnotesize}
\caption{\footnotesize{struct subsystem methods.}}
\end{table}

Struct subsystem contains an embedded kobject to contain generic
objects meta data about the subsystem itself. This is also to
represent the subsystem's membership in another subsystem. 

The subsystem object contains a list that registered objects are
inserted on. 'rwsem' is a semaphore that protects access to the
list. It should always b e taken before iterating over the list, or
adding or removing members. 

Subsystems are believed to be hierarchical, as some subsystems contain
subordinate subsystems or containers of objects.  The 'parent' field
may be used to denote a subsystem's ancestral parent.


'sysfs\_ops' is a pointer to a set of operations that a subsystem must
define to read and write attributes that are exported for subordinate
kobjects via the sysfs filesystem. 'default\_attrs' is a
NULL-terminated array of attributes that are unconditionally exported
for every kobject registered with the subsystem. sysfs is discussed,
and these fields will be covered, in the next section.


The 'release' method is defined as a means for the subsystem to tear
down a kobject registered with it. A subsystem should implement this
method. When a kobject's reference count reaches 0, kobject\_cleanup()
is called to tear down the device. That reference's the kobject's
subsystem and its 'release' method, which it calls to allow the
subsystem to tear down the device (Since the subsystem likely embedded
the kobject in something larger, and it must convert to it.).



\subsection*{Programming Interface}


Subsystems  provide a similar programming model to kobjects. However,
they allow only simple register() and unregister() semantics, and do
not export the intermediate calls for the rest of the kernel to use.
Also , a subsystem's reference count may be incremented using
subsys\_get() and decremented using subsys\_put(). 


\begin{table}
\begin{footnotesize}
\begin{tabularx}{\linewidth}{|X|X|X|} \hline
\textit{Name}	& \textit{Return Type} & \textit{Description} \\ \hline \hline

subsystem\_register(struct subsystem *)
& int
& Initialize subsystem and register embedded kobject.
\\\hline

subsystem\_unregister(struct subsystem *)
& void
& Unregister embedded kobject.
\\\hline

subsys\_get(struct subsystem *)
& struct subsystem *
& Increment subsystem's reference count.
\\\hline

subsys\_put(struct subsystem *)
& void 
& Decrement subsystem's reference count. 
\\\hline

\end{tabularx} 
\end{footnotesize}
\caption{\footnotesize{struct subsystem Programming Interface.}}
\end{table}

