This is a pure userspace and login issue. Problems will arise from ftp or
other services authenticating you though, because ftpd would also need to
know as which group member to do file access. It could use ~/.group as
well or use some site specific FTP extension, again a user space issue.
I still won't suggest anyone to do it as it is pretty non standard.
With regards to NGROUPS, I'm sure it can be easily raised. It might be
possible to handle it fully dynamic, but you still want to have a hard
limit to stop a gone mad process to be in a set of almost 2^32 groups.
Also there is a performance issue, any file access will have to loop
through the list of groups to determine if you have access or not, so you
want to keep the list small. If longs lists of group were allowed I'm sure
one can optimize this with a binary search in a sorted list of groups, but
this won't help much in conjunction with ACL's then.
I am a 26 yo. super good looking guy, I have awesome ripped, muscular and smooth bod, I would like to put on a erotic show for woman only. I am playgirl centerfold material and want to show it off. Nothing is expected of you just enjoy the show. Not looking for sex just turns me on to be watched.
You're so mean, now I'm crying like a little girl.
My evil subterfuge is unsuccessful under a bitch slapped account. The challenge is, can you spot the plagiarized posts? Some mods on crack sure can't, +5 all around the fuckin place. bznatchs!
STANDARDIZED TROLL REPLY FORM
(original by Spootnik)
I took exception to your recent _X_ comment to __slashdot______
___ story
It was (check all that apply):
___ first post.
___ ascii art.
___ karma whore.
___ modded on crack.
___ counter lameness filter.
___ racist.
_X_ raging homosexual.
___ much longer than any worthwhile thought of which you may be capable.
Your attention is drawn to the fact that:
_X_ what you posted/said has been done before.
(Mark only if above checked)
___ Not only that, it was also done better the last time.
___ your post/letter was a pathetic imitation of ____________________.
(net.personality)
___ your post/mail originated on AOL.
___ your post/mail originated from the anon service
_X_ your post/mail originated from a commercial service unwise enough to
take your money
(Mark only if above checked)
_X_ you felt this gave you a license to be a 'tard
(Mark only if above checked)
___ your stupidity will be reported to jamie@mccarthy.vg per
the crackhead disclaimer under "excessive bad posting"
___ your post referred to the slashdot as a reliable source of information.
___ you posted a boring anecdote about your nerdy behaviours.
___ you posted a request for sexual favor.
___ you posted a pointer to goatse.cx
___ you asked for dirty pictures.
___ you posted a personal ad to a personal web site
___ you posted a request for a Beowulf cluster of that.
___ you posted a request for Nathalie Portman
___ Naked and petrified.
___ you poored hot grits down your pants.
___ you are not wearing pants.
___ your post contained numerous spelling errors.
___ including the subject line
___ your post contained multiple grammatical errors.
___ YOUR POST CONTAINED EXCESSIVE CAPITALIZATION AND/OR PUNCTUATION!!!!!
___ you posted a spelling and/or grammar flame.
(Mark only if above checked)
___ and you made spelling and/or grammatical errors.
_X_ you have a lame login name.
___ you quoted an article in followup and added no new text.
___ you quoted an article in followup and only added ___ lines of text.
___ you posted an identical article multiple times.
___ you apologized claiming a problem with your brain.
___ you followed up a spam or a chain letter and included it in its entirety.
___ you quoted an article in followup and only added the line "Me, too!!!"
___ you predicted the "Imminent Death of BSD".
___ you flamed someone who has mentionned the word "Microsoft".
___ you filthy hippy bragged about the all mighty Linux.
___ you failed to read the article.
___ your.sig is longer than four lines.
(Mark only if above checked)
___ And the lameness filter truncated it.
___ your.sig is ridiculous because (check all that apply):
___ you listed ___ email addresses for trolls to use in prank posts.
___ you included a stupid disclaimer.
(Mark only if above also)
___ your pathetic attempt at being witty in the disclaimer failed.
(Mark only if above also)
___ Miserably.
___ you included:
(Mark all that apply)
___ a stupid self-quote.
___ a stupid quote from 1st amendment.
___ a Star Trek quote.
___ a lameass joke.
___ a reference to Osama Bin Laden.
Furthermore:
___ You have greatly misunderstood the purpose of ________________________.
___ You have greatly misunderstood the purpose of masturbating.
___ You are a loser.
___ You must have spent your entire life in a skinner box to be this clueless.
___ *plonk*
___ This has been pointed out to you before.
_X_ Propz to all my dead homiez.
_X_ It is recommended that you:
(Mark all that apply)
___ stick to Adequacy and come back when you've grown up.
___ find a volcano and throw yourself in.
___ get a gun and shoot yourself.
___ stop reading Salshdot news and get a life.
___ stop posting comments and get a life.
_X_ consume excrement.
___ consume excrement and thus expire.
Joe Sixpack is a fool. I'm supar important, ya know what I mean, ya know what I'm sayin. I called da lead o' da project n' he wazin da tank checking out da damage. White boyz in da house.
I'm sure there would be plenty of volunteers for a
'Luxo Jr Restoration Project'... It would have to be
a pretty hard task otherwise;)
It would be an extremely cool thing to do. Maybe we could
rival the IRTC Group Image Project (GIP) with a c.g.r.r.
Luxo Jr Restoration Project (LJRP)?
That said, I still find that the animation in Luxo is
rather impressive. Despite lacking the physical "realness"
of modern productions, some of it is very nice: like the
power lead ripples, and when Jr goes bouncing on the ball
for all he's worth...:-) The character expression is
really good.
The big studios invest considerable
resources into streamlining these to avoid having an hour of every
frame just for shipping texture tiles over the network. It's a
struggle, even with high-speed lines all in the same building. That's
why the idea of trying to ship the data off-site is so ludicrous.
I'd love to see the back-of-the-envelope calculations for how much
bandwidth a real scene would take, how many machines "out there" would
have the resources to handle it. If the argument is that you're not
talking about studio films or other large projects, but rather small
hobby projects, then work backwards from the available bandwidth and
resources to deduce exactly what kind of scene might be practical.
These appear to be libraries, not an actual player. I'll search around
later, but I suspect if folks are looking for a QuickTime player they may be
disappointed.
Look for a program called 'xanim' for starters. Another
app which _might_ have quicktime support is 'xmms'.
It's pretty amazing. After hearing a lot about it, I caught the short on,
of all places, C-SPAN, in the middle of a speech by Steve Jobs, now one of
the Pixar mucky-mucks after plucking Apple off the tree.
It's too bad studios don't attach shorts to features very often--there was
that brief run of Roger Rabbit 'toons there for a while, and Disney slips us
a Mickey from time to time, but that's about it, innit?
See, once upon a time George Lucas had this little toy
of a company that produced computer animation, but he unloaded it in order
to focus on more important things like "Howard the Duck". The company,
called Pixar, did things like produce commercials and trade show tidbits and
the like, but also started working on original animated shorts. One of
these, called "Tin Toy", got the attention of the huge entertainment
conglomerate known as "Disney", who knew that the filmgoing public would
eventually tire of such classics as "The Black Cauldron" and "The Rescuers
Down Under", seeing as how (unlike most film styles) traditional cel
animation had not really evolved or improved significantly over its history.
Disney made a deal to distribute Pixar's films for a share of the profits.
The first of these films, "Toy Story", was a relatively unexpected success
and made a lot of money for Disney. After this, Pixar insisted on
renegotiating the deal to get more $$$$ for their efforts and to get equal
billing in all advertising materials. Eventually, look for Pixar to
distribute their own films, much the way Disney took over from RKO when they
wanted more control and $$$$, and for Disney to produce their own
computer-animated films.
Putting the 2MX core on that board is a clear sign of intent at
creating an integrated gaming machine (it is the largest market for
3D applications by a _long_ way). Nvidia haven't had a problem
targetting the higher end before now, so why are they just utterly
ignoring it now? CaseyB ate my balls. I'm not saying the current nForce is a bad idea,
but it is a little late and I fear the target market have already
just bought 2MX's instead.
nVidia's strategy is clear though. Get 2MX's on the desktop so people
can see 3D game show they might be, then sit back and wait for the
next gen GF3 and X-box ports to come along, and suddenly your now
switched on to 3D audience wants GeForce 3.
Their current roadmap still has them at 2.4Ghz next summer. At that rate, I
seriously doubt they will have a 3Ghz out before the end of the year. I bet 3Ghz
isnt released until some time near the end of the first half of 2003.
Intel demonstrated a Northwood P4 running at 3Ghz with _supercooling_. (it actually
got up to 3.5Ghz, but the demos were run at 3Ghz). Who the hell told you Intel had
a P4 running at 5Ghz?
Yeah, they could probably make it to 10Ghz within 3 years pretty easily if they use
the same design concept behind the current P4. Maybe they will increase the
pipeline to 40 stages and get there even faster!
Oh boy.. Clock speed isn't everything. The P4 architecture is brilliant for a
company trying to sell their CPUs to people like you. The chips are a hell of a lot
easier to market when people just look at the clock speed.
Rambus has little to do with being able to run between 3 and 10Ghz. Intel just
doesnt want to admit that after spending all this time doing nothing but saying
RDRAM is the only way.
AMD already has.13 capability and the new SOI technology to go with it. They will
be sampling Thoroughbred processors next quarter.
Since you care so much about your all mighty karma points, why don't you go hang out with Oprah Winfrey or something. Leave us the fuck alone, biznatch!
Multitasking involves the computer doing more than one thing at the
same time. You can produce this situation in a variety of ways,
but they all amount to the same thing: multiple executution
contexts (PCs, SPs, & other registers) with some degree of sharing.
When you use
$kid = open(CHILD, "cmd args |");
your begotten child process shares a few file descriptors, umasks,
process group, and credentials with the original process. In fact,
nearly everything is shared. Only text, data, pid, and register
set vary.
When you use
$kid = open(MYSELF, "|-");
or
$kid = fork();
You end up sharing a bit more -- the backing store text is now the same,
but data, pid, and register set are distinct. You can open particular
communications mechanisms between the entities, such as pipes and
shared memory, but the default on data space is separate but equal.
Text pages are still shared.
People have been using fork() to write multithreaded (read: multitasking)
applications on Unix for about twenty-five years. It is a simple and
powerful model that has withstood the test of time. It is also highly
optimized, using such cleverness as copy-on-write for the data and
making use of special machine hardware designed to facilitate
context switches and page table manipulations.
Another scenario is the so-called "light-weight process". Various
implementations have taken different approaches to these. One that stands
out as different from many of the current crowd was the Convex C-series,
where FORK and JOIN were hardware instructions to create a new execution
thread without any operating system intervention whatsoever. This was
beneficial in cases where you in effect wanted highly parallizable
vector processing distributed across several CPUs where everything else
was shared. Each thread had separate thread registers, and the operating
system could consult special thread state accumulators when the whole
process ended. This tightly-knit relationship between the hardware
designers, operating system designers, and compiler designers produced
some intriguing possibilities not seen on commodity systems.
The typical use of the word "thread" now has varied greatly from its
original use, which was essentially synonymous with a fork()d process.
(And these new light-weight processes aren't always particularly light in
weight, either.) I assume you are using "thread" in the vernacular,
which most often seem to mean to create a new context where everything
is shared just as in a fork, except this time, all data space will also
be jointly accessible.
In short, with fork(), data space is protected unless you say otherwise
(such as with IPC::Shareable) whereas with Thread::->new, it's an
uncontrolled free-for-all. I can certainly see why you might wish to
have several active PCs running concurrently, but I am dubious that you
have an application for which uncontrolled, unmediated sharing amongst
these threads would be a natural solution not easily accomplishable
using the protected threads you get when you fork.
Prisoners of Microsoft tend to leap to solutions that involve
(data-)unprotected threads rather than those that involve (data-)protected
ones. This is the wrong thing to do. But they do it because an
efficient implementation requires a sound underlying theorectical model,
and Microsoft has never shown itself adept at operating systems design.
Linux protected threads (read: "processes") context-switch many times
faster on the same hardware than do Microsoft's unprotected ones (read:
"threads").
This old statement of mine is applicable in many contexts, including
the current one:
"In short, just as the Multics mentality of careful access controls
shows up throughout Unix, the cretinous CP/M mentality of uncontrolled
havoc shows up in DOS and all its mutant children." --tchrist
I'll finish up by including an interesting article that turned up in
a thread on comp.unix.programmer. There's a good bit of noise there,
but also some interesting technical data as well.
I cannot speak for other BSDs, but in BSD/OS 4.0, the model (the
code is not yet fully implemented) is that the sfork() call --
essentially the same as Plan 9's rfork() and Linux's clone() --
is the "one true" process creator. (Process 0, which forks init
and does other similar work during bootstrapping, is never really
"created": it exists in the/bsd image as loaded, modulo some
hookups needed at boot time.) There are compatibility routines,
as in any other system-with-historical-baggage, of course.
Putting aside the fundamental misunderstanding that "Ed@eds.net"
apparently had when he started trol-- er, I mean began this
discussion,:-) one way to view the whole idea is this. Note that
the terminology differs from that used when describing traditional
Unix systems.
There is no such thing as a "process", there is just a "thread".
Here a "thread" is really just an ID, some optionally-shared
resources like memory and files, and maybe a kernel stack or
some such -- pretty much the same thing as a Unix "process".
"Fork" just creates a new thread; everything is shared. [Note
that the new thread *does* need a way to know that it is in fact
the new one. How this is achieved is not particularly important
in terms of the model.]
Any thread can request that some of its currently-shared
resources can become "unshared" (have a private copy made, so
that changes to them will not change someone else's copy).
[In Plan 9, Linux, and the various BSDs, these operations are
rolled into the argument to [rs]fork/clone; logically, they
should probably be separate. One can make efficiency
arguments, but see below.]
In addition:
Any thread can wipe itself out and run some other executable
image instead (Unix "exec"). This wipes out any parts of memory
not marked "preserve across exec"[%], partly just to match
tradition, partly for ease of implementation, and partly for
security when executing setuid binaries. (In other words, it
does not *have* to be done this way. Given that current hardware
tends to implement binaries that tend not to be entirely
position-independent, we make concessions to efficiency here.
We say: "We could not figure out how to make the old image
hang around while the new image is loaded, and then give the
old image a chance to remove itself if that is what it intended.
So even though it looks like this action is made of a bunch of
simpler atomic actions, we could not figure out a nice way to
break it down.")
[% Some systems have no way to mark any such sections, in which
case *all* memory "goes away" on exec. This is why exec takes
argv and envp: to pass *some* data across the operation. "Leave
memory region R" alone would suffice for the same purpose, and
could be more efficient -- perhaps substantially so.]
Now, one can argue that "make a thread-copy and immediately exec",
which is the pair of primitives that emulates other OS's "create
new process running program P" operation, ought to be less efficient
than simply having a "create new process running program P" operation
(whether that is spelled spawn() or CreateProcess() or SYS$CREPRC
or whatever -- let me use spawn() here for short). That argument
makes some sense to me. Given a thread+exec model, fundamentally,
spawn() is just "create thread, then exec". If there is any overhead
in returning to user code, then having the user code immediately
turn around and exec, all of that overhead can be eliminated.
But if you take a look at otherwise "reasonably comparable" systems
that *do* offer "spawn" instead of fork+exec, something strange
happens. The overhead for processes in those systems turns out to
be *greater* than it is in the Unix-like systems. (Examples: VMS
vs 4.1BSD on a VAX; NT vs Linux on an x86.) This overhead leads
people to write "all in one" packages on the "spawn" systems (e.g.,
the directory lister is usually built into the user interface),
while the relative lack of overhead in the fork+exec systems leads
people to write smaller "tool" programs (the directory lister is
usually a separate program, and hence works with pipes and "wc"
word counters and "lpr" printer spooling and so on[%]). Perhaps
the people who wrote the spawn() systems were just not as good as
the people who wrote the fork+exec systems, but in any case, it
seems odd.
[%] A friend of mine suggests that you try "telling your mom" (or
any suitable non-computer-geek type) how to print out a listing
of files in some particular directory. On Unix systems: run
"ls -l | lpr".
Now for many side points, even if one of them was the main point
of the original article. First, removing all the biasing wording:
There are two reasons for having a parent/child relationship in
fork().
First, we need to distinguish between the original thread (process)
and the new thread (process). We can arbitrarily label the original
the "parent" and the new clone the "child". Or we could label them
"old" and "new", or "Fred" and "Barney", or whatever, but "parent"
and "child" works.
Second, any time any program runs any other program, it *might*
care whether that other program succeeds. If there is *no*
relationship between old and new, as suggested above, there is also
no way for the creator to get information on the createe. So there
must be *some* relationship: even if it is not a tree-structured
parent/child thing, at the very least there is a "creator/createe"
relationship, from the very fact that one process spawned the other.
Using a parent/child relationship, and tying it to the return value
from fork() (the thread/process id), is probably the simplest way
of expressing this. Even when you are not doing cloning -- even
when the only call you have is spawn() -- there is still a "creator"
(spawner) and "createe" (spawnee), and those remain "parent" and
"child", whether or not the OS tracks it.
"Natural" is one of those "marketing" type words that people use
to sell one shampoo vs another (ours contains 2,4-di-poly-... so
ours is More Natural!). But if you want to have a ProcessManager
do the creating, you can code that yourself on any modern Unix
system. Just write a program that listens for IPC requests to
create new processes. Run it once, then send those IPC requests.
The listening program is your ProcessManager and the IPC requests
invoke it.
Problem solved. Next?:-)
If you like the taste of ice cream more than that of vegetables,
nothing anyone can say about the health qualities of either is
going to change your mind about which tastes better.
In some systems, there are definite "right" vs "wrong" answers.
"Everyone knows" that objects are naturally at rest -- if I roll
a baseball on the ground, it always stops rolling eventually --
but in physics, Aristotle was wrong; Newton supplied a "righter"
model. In this case, however, you have set up a system in which
only you can possibly be right: "By `right' I mean something fits
my intuition. A process manager fits my intuition, so any other
model is wrong." There is nothing to prove or disprove here; you
are letting your intuition dictate the answer, and your intuition
is yours alone.
If so, you will have to come up with more objective criteria.
This is not a good mental model for Unix systems, and indeed, not
a good mental model for many other non-Unix-like systems. To stick
with traditional Unix systems (where fork() is "create new kernel
thread, and immediately unshare all user memory"), a "process" is
made up of:
an identifier (Process ID or "pid");
an address space (which might map to a.exe, or might not;
the exec() call always creates such a mapping, but once exec'ed,
a process can generate and/or load new code and data [a la a "DLL"
in Microsoft-ese], and/or toss out its existing code and data,
as long it is careful);
file descriptors (references to open files/pipes/IPC);
credentials (~= privileges);
resource limits;
any other things I cannot think of off the top of my head.
Any process can change or rearrange any of these except its PID:
the PID is the outside world's "true name" for the process. (The
kernel might use a data pointer inside, if that seems more efficient
and/or appropriate, but the outside-world name is the PID.)
At the OS level, there is only fork() and exec(); system() is a C
library (non-OS-level) thing. Clone() is just fork() spelled
sideways, and the sideways spelling is just to work around the fact
that, historically, fork() implies "copy (do not share) the
resources", which tends to be slow. (Copy-on-write helps a lot,
but not so much that people are not still drawn to some other
mechanism, whether it is the limited vfork() or the flexible
sfork()/rfork()/clone(), to avoid the copy altogether.) If you
prefer, fork() is just clone() spelled sideways; as noted way at
the top, the true primitive is "make a new thread with everything
shared".
Now, once you have made the new, all-shared thread, you can do this
in the "new" thread (as a shell might, to do "ls | wc"):
1 split off the file descriptors
2 create a pipe
3 make another new, all-shared thread
[new thread only, again]
3a split off the file descriptors
3b close the read side of the pipe
3c move the write side of the pipe to STDOUT_FILENO
3d exec "/bin/ls"
[NOTREACHED]
4 close the write side of the pipe
5 move the read side of the pipe to STDIN_FILENO
6 exec "/usr/bin/wc"
The "split off the file descriptors" steps are required so that
the new thread does not change or close the old thread's (shared)
descriptors, which in step (2) would make the pipe available to
the shell itself (the shell does not want it), and in step (3b)
would remove "wc"'s access to the read side of the pipe (which
would be disastrous).
(Since rfork/clone take an argument, steps 1 and 3a are actually
implicit, via "pid = xyzzyfork(SHARE_ALL_BUT_DESCRIPTORS)". That
means the process above is actually 8 steps long -- 9 if you add
in the initial fork.)
Note that a parent/child relationship occurs between "ls" and "wc"
here, even though neither program wants it. This is not a *problem*,
but it has no advantage either; it is just a side effect of the
order of user-level manipulations involved in connecting the output
of "ls" to the input of "wc". If the shell wants to be the parent
of both ls and wc, the "make a pipe" step has to occur earlier and
the sequences needs to be slightly different. (In fact, old versions
of the Bourne shell used the above sequence, while modern shells
*do* create the pipe earlier and remain the parent of each process
in the pipeline.)
The "traditional spawn()" model looks like this:
1 create a pipe
2 move the current STDOUT_FILENO out of the way
3 move the write side of the pipe to STDOUT_FILENO
4 spawn "/bin/ls"
5 close the write side of the pipe
6 move the current STDIN_FILENO out of the way
7 move the read side of the pipe to STDIN_FILENO
8 spawn "/usr/bin/wc"
9 close the read side of the pipe
10 move the saved STDIN_FILENO back
11 move the saved STDOUT_FILENO back
In other words, it takes 11 steps, not 9, with a "spawn" model.
Even though the fork and exec steps are combined (saving one step
per fork+exec pair on the Unix shell side), the number of steps
does not go down. The reason is that the spawner must do all the
manipulation up front: there is no chance to change things around
between the "create new process" step and the "take flying leap
into new object file" step.
There is really very little to draw. Whoever calls fork() is a
parent. The clone copy is a child.
But sales figures, naturally, don't tell the whole story. Of equal (or more)
importance would be net margins, and Microsoft maintains better margins than
almost any other large company in existence. For example, GM had $161B in
sales last year - pretty big, right? But auto manufacturing is a very
low-margin business - they had just 1.8% net margins, or about $3B in profit.
By contrast, Microsoft had 36% net margins last year, or over $5B in profit,
well exceeding GM. They also (just) exceeded Wal-Mart's profits for last
year, beating out another Dow component. That's 3 of the Dow 30... I haven't
checked the other 27, but I'd bet MS turned more profit than most of those as
well, and had just as comparable sales numbers.
Sure, Bill's money has to come from somewhere. Their profits are
impressive -- but generated by monopoly sales in a booming market and
therefore threatened by state intervention as well as future
competition. This isn't the same as a margin of 1.8% in a mature
competitive environment.
GM is already considered mismanaged as compared to Ford and Chrysler,
and their margin may be expected to grow if they get their act
together. MS's margin, OTOH, can only reasonably be expected to fall
in the long run, for whichever of a whole variety of reasons
(increasing development costs and market saturation come to mind
besides what's mentioned above).
More impressive to me, by far, is that Microsoft currently has somewhere
around $20 billion in cash reserves, depending on which day you look. In
other words, they have over a year's worth of sales, in cash, on hand, with no
debt whatsoever. I don't think they're going anywhere anytime soon. In fact,
the cash alone accounts for 5-10% of their stock price, again depending on
what day you look.
Fundamentally speaking, having 5-10% of the stock price backed by
assets still leaves 90-95% uncovered. How many assets does Microsoft
own besides their cash, anyway? They don't own manufacturing plants
or oil platforms or warehouses full of tangible durable goods, just
some buildings with a bunch of PCs and rapidly outdated software.
Seriously, though, stock prices aren't only driven by raw sales or profit
numbers; far from it. They're driven by *growth* as well. Is Microsoft, as
big as they are, growing faster than Wal-Mart? You damn skippy they are.
BSD contained the freely available reference implementation of
IPv4. Chameleon and espescially Trumpet were the companies that
actually shipped working IP suites for Windows, and who let the
Windows-masses get on the net in the first place. There wouldn't
have been a demand for Windows TCP/IP if Trumpet and Chameleon
hadn't created it. Microsoft was set up to use MSN to duke it out
with AOL and Compuserve for dialins into proprietary networks, not
to deal with the internet. Until, of course, all their users suddenly
said "Hey, we like the open Internet." And then it still took them
a year or so to notice.
The BSD TCP/IP code, or code based on it, is present on every single
Windows and most every Unix Internet-attached computer in the world.
That's a pretty big "install base," and easily musters most current
internet users. Chameleon and Trumpet had 99% of the Windows TCP/IP
install base until Windows 95, and still have all of the Windows
TCP/IP install base for everyone who has not yet upgraded past
Windows 3.11 and a substantial amount of the people still running
earlier versions of Windows 95 who kept using them instead of
Microsoft's implementation.
Mythical man month is a very good book. It was written by a key figure
in IBM's development of IBM's S/360 OS. He gives very good advice on
planning and developing data processing systems.
His basic premise is that a man and month are NOT interchangeable. That
is, a project requiring 1 person working 6 months can NOT be converted
to 6 people working 1 month.
Frederick P. Brooks, Jr.
the mythical man-month
Essays on Software Engineering
Addison-Wesley ISBN 0-201-00650-2
If you can't find a copy of the lecture specifically, I am sure that Dr. Brooks covers all the same
grounds in the 20th anniversary edition of "The Mythical Man-Month" pub Addison-Wesley
ISBM0-201-83595-9.
I think one of the reasons people become so enthralled with the
economic/political philosophy of Linux (as opposed to the people who use
Linux, because, hey, free UNIX) is because it does something extremely
rare (I would say unprecedented) politically.
This is a pure userspace and login issue. Problems will arise from ftp or other services authenticating you though, because ftpd would also need to know as which group member to do file access. It could use ~/.group as well or use some site specific FTP extension, again a user space issue.
I still won't suggest anyone to do it as it is pretty non standard.
With regards to NGROUPS, I'm sure it can be easily raised. It might be possible to handle it fully dynamic, but you still want to have a hard limit to stop a gone mad process to be in a set of almost 2^32 groups. Also there is a performance issue, any file access will have to loop through the list of groups to determine if you have access or not, so you want to keep the list small. If longs lists of group were allowed I'm sure one can optimize this with a binary search in a sorted list of groups, but this won't help much in conjunction with ACL's then.
I am a 26 yo. super good looking guy, I have awesome ripped, muscular and smooth bod, I would like to put on a erotic show for woman only. I am playgirl centerfold material and want to show it off. Nothing is expected of you just enjoy the show. Not looking for sex just turns me on to be watched.
You're so mean, now I'm crying like a little girl.
My evil subterfuge is unsuccessful under a bitch slapped account. The challenge is, can you spot the plagiarized posts? Some mods on crack sure can't, +5 all around the fuckin place. bznatchs!
STANDARDIZED TROLL REPLY FORM
.sig is longer than four lines. .sig is ridiculous because (check all that apply):
(original by Spootnik)
I took exception to your recent _X_ comment to __slashdot______
___ story
It was (check all that apply):
___ first post.
___ ascii art.
___ karma whore.
___ modded on crack.
___ counter lameness filter.
___ racist.
_X_ raging homosexual.
___ much longer than any worthwhile thought of which you may be capable.
Your attention is drawn to the fact that:
_X_ what you posted/said has been done before.
(Mark only if above checked)
___ Not only that, it was also done better the last time.
___ your post/letter was a pathetic imitation of ____________________.
(net.personality)
___ your post/mail originated on AOL.
___ your post/mail originated from the anon service
_X_ your post/mail originated from a commercial service unwise enough to
take your money
(Mark only if above checked)
_X_ you felt this gave you a license to be a 'tard
(Mark only if above checked)
___ your stupidity will be reported to jamie@mccarthy.vg per
the crackhead disclaimer under "excessive bad posting"
___ your post referred to the slashdot as a reliable source of information.
___ you posted a boring anecdote about your nerdy behaviours.
___ you posted a request for sexual favor.
___ you posted a pointer to goatse.cx
___ you asked for dirty pictures.
___ you posted a personal ad to a personal web site
___ you posted a request for a Beowulf cluster of that.
___ you posted a request for Nathalie Portman
___ Naked and petrified.
___ you poored hot grits down your pants.
___ you are not wearing pants.
___ your post contained numerous spelling errors.
___ including the subject line
___ your post contained multiple grammatical errors.
___ YOUR POST CONTAINED EXCESSIVE CAPITALIZATION AND/OR PUNCTUATION!!!!!
___ you posted a spelling and/or grammar flame.
(Mark only if above checked)
___ and you made spelling and/or grammatical errors.
_X_ you have a lame login name.
___ you quoted an article in followup and added no new text.
___ you quoted an article in followup and only added ___ lines of text.
___ you posted an identical article multiple times.
___ you apologized claiming a problem with your brain.
___ you followed up a spam or a chain letter and included it in its entirety.
___ you quoted an article in followup and only added the line "Me, too!!!"
___ you predicted the "Imminent Death of BSD".
___ you flamed someone who has mentionned the word "Microsoft".
___ you filthy hippy bragged about the all mighty Linux.
___ you failed to read the article.
___ your
(Mark only if above checked)
___ And the lameness filter truncated it.
___ your
___ you listed ___ email addresses for trolls to use in prank posts.
___ you included a stupid disclaimer.
(Mark only if above also)
___ your pathetic attempt at being witty in the disclaimer failed.
(Mark only if above also)
___ Miserably.
___ you included:
(Mark all that apply)
___ a stupid self-quote.
___ a stupid quote from 1st amendment.
___ a Star Trek quote.
___ a lameass joke.
___ a reference to Osama Bin Laden.
Furthermore:
___ You have greatly misunderstood the purpose of ________________________.
___ You have greatly misunderstood the purpose of masturbating.
___ You are a loser.
___ You must have spent your entire life in a skinner box to be this clueless.
___ *plonk*
___ This has been pointed out to you before.
_X_ Propz to all my dead homiez.
_X_ It is recommended that you:
(Mark all that apply)
___ stick to Adequacy and come back when you've grown up.
___ find a volcano and throw yourself in.
___ get a gun and shoot yourself.
___ stop reading Salshdot news and get a life.
___ stop posting comments and get a life.
_X_ consume excrement.
___ consume excrement and thus expire.
Additional comments:
None needed.
Not being retarded.
Your left nut tastes like chicken. Slashdot makes me want to toss your salad.
WTF does your mom do your shopping for you? You are freaking me out!
Joe Sixpack is a fool. I'm supar important, ya know what I mean, ya know what I'm sayin. I called da lead o' da project n' he wazin da tank checking out da damage. White boyz in da house.
I'm sure there would be plenty of volunteers for a 'Luxo Jr Restoration Project'... It would have to be a pretty hard task otherwise ;)
:-) The character expression is
really good.
It would be an extremely cool thing to do. Maybe we could rival the IRTC Group Image Project (GIP) with a c.g.r.r. Luxo Jr Restoration Project (LJRP)?
That said, I still find that the animation in Luxo is rather impressive. Despite lacking the physical "realness" of modern productions, some of it is very nice: like the power lead ripples, and when Jr goes bouncing on the ball for all he's worth...
The big studios invest considerable resources into streamlining these to avoid having an hour of every frame just for shipping texture tiles over the network. It's a struggle, even with high-speed lines all in the same building. That's why the idea of trying to ship the data off-site is so ludicrous.
I'd love to see the back-of-the-envelope calculations for how much bandwidth a real scene would take, how many machines "out there" would have the resources to handle it. If the argument is that you're not talking about studio films or other large projects, but rather small hobby projects, then work backwards from the available bandwidth and resources to deduce exactly what kind of scene might be practical.
I performed a search on google and found:
http://www.appwatch.com/Linux/App/1170/data.html
http://heroinewarrior.com/quicktime.php3
These appear to be libraries, not an actual player. I'll search around later, but I suspect if folks are looking for a QuickTime player they may be disappointed.
Look for a program called 'xanim' for starters. Another app which _might_ have quicktime support is 'xmms'.
It's pretty amazing. After hearing a lot about it, I caught the short on, of all places, C-SPAN, in the middle of a speech by Steve Jobs, now one of the Pixar mucky-mucks after plucking Apple off the tree.
It's too bad studios don't attach shorts to features very often--there was that brief run of Roger Rabbit 'toons there for a while, and Disney slips us a Mickey from time to time, but that's about it, innit?
See, once upon a time George Lucas had this little toy of a company that produced computer animation, but he unloaded it in order to focus on more important things like "Howard the Duck". The company, called Pixar, did things like produce commercials and trade show tidbits and the like, but also started working on original animated shorts. One of these, called "Tin Toy", got the attention of the huge entertainment conglomerate known as "Disney", who knew that the filmgoing public would eventually tire of such classics as "The Black Cauldron" and "The Rescuers Down Under", seeing as how (unlike most film styles) traditional cel animation had not really evolved or improved significantly over its history. Disney made a deal to distribute Pixar's films for a share of the profits. The first of these films, "Toy Story", was a relatively unexpected success and made a lot of money for Disney. After this, Pixar insisted on renegotiating the deal to get more $$$$ for their efforts and to get equal billing in all advertising materials. Eventually, look for Pixar to distribute their own films, much the way Disney took over from RKO when they wanted more control and $$$$, and for Disney to produce their own computer-animated films.
Putting the 2MX core on that board is a clear sign of intent at creating an integrated gaming machine (it is the largest market for 3D applications by a _long_ way). Nvidia haven't had a problem targetting the higher end before now, so why are they just utterly ignoring it now? CaseyB ate my balls. I'm not saying the current nForce is a bad idea, but it is a little late and I fear the target market have already just bought 2MX's instead.
nVidia's strategy is clear though. Get 2MX's on the desktop so people can see 3D game show they might be, then sit back and wait for the next gen GF3 and X-box ports to come along, and suddenly your now switched on to 3D audience wants GeForce 3.
Their current roadmap still has them at 2.4Ghz next summer. At that rate, I seriously doubt they will have a 3Ghz out before the end of the year. I bet 3Ghz isnt released until some time near the end of the first half of 2003.
.13 capability and the new SOI technology to go with it. They will
be sampling Thoroughbred processors next quarter.
Intel demonstrated a Northwood P4 running at 3Ghz with _supercooling_. (it actually got up to 3.5Ghz, but the demos were run at 3Ghz). Who the hell told you Intel had a P4 running at 5Ghz? Yeah, they could probably make it to 10Ghz within 3 years pretty easily if they use the same design concept behind the current P4. Maybe they will increase the pipeline to 40 stages and get there even faster!
Oh boy.. Clock speed isn't everything. The P4 architecture is brilliant for a company trying to sell their CPUs to people like you. The chips are a hell of a lot easier to market when people just look at the clock speed. Rambus has little to do with being able to run between 3 and 10Ghz. Intel just doesnt want to admit that after spending all this time doing nothing but saying RDRAM is the only way.
AMD already has
Since you care so much about your all mighty karma points, why don't you go hang out with Oprah Winfrey or something. Leave us the fuck alone, biznatch!
Actually the links contain a biometric signature of your genitals, and let me tell you, sir, you have a tiny dick. *sigh*
Hello, I'm Dr. Squiffy.....
When you use
$kid = open(CHILD, "cmd args |");
your begotten child process shares a few file descriptors, umasks, process group, and credentials with the original process. In fact, nearly everything is shared. Only text, data, pid, and register set vary.
When you use
$kid = open(MYSELF, "|-"); or $kid = fork();
You end up sharing a bit more -- the backing store text is now the same, but data, pid, and register set are distinct. You can open particular communications mechanisms between the entities, such as pipes and shared memory, but the default on data space is separate but equal. Text pages are still shared.
People have been using fork() to write multithreaded (read: multitasking) applications on Unix for about twenty-five years. It is a simple and powerful model that has withstood the test of time. It is also highly optimized, using such cleverness as copy-on-write for the data and making use of special machine hardware designed to facilitate context switches and page table manipulations.
Another scenario is the so-called "light-weight process". Various implementations have taken different approaches to these. One that stands out as different from many of the current crowd was the Convex C-series, where FORK and JOIN were hardware instructions to create a new execution thread without any operating system intervention whatsoever. This was beneficial in cases where you in effect wanted highly parallizable vector processing distributed across several CPUs where everything else was shared. Each thread had separate thread registers, and the operating system could consult special thread state accumulators when the whole process ended. This tightly-knit relationship between the hardware designers, operating system designers, and compiler designers produced some intriguing possibilities not seen on commodity systems.
The typical use of the word "thread" now has varied greatly from its original use, which was essentially synonymous with a fork()d process. (And these new light-weight processes aren't always particularly light in weight, either.) I assume you are using "thread" in the vernacular, which most often seem to mean to create a new context where everything is shared just as in a fork, except this time, all data space will also be jointly accessible.
In short, with fork(), data space is protected unless you say otherwise (such as with IPC::Shareable) whereas with Thread::->new, it's an uncontrolled free-for-all. I can certainly see why you might wish to have several active PCs running concurrently, but I am dubious that you have an application for which uncontrolled, unmediated sharing amongst these threads would be a natural solution not easily accomplishable using the protected threads you get when you fork.
Prisoners of Microsoft tend to leap to solutions that involve (data-)unprotected threads rather than those that involve (data-)protected ones. This is the wrong thing to do. But they do it because an efficient implementation requires a sound underlying theorectical model, and Microsoft has never shown itself adept at operating systems design. Linux protected threads (read: "processes") context-switch many times faster on the same hardware than do Microsoft's unprotected ones (read: "threads").
This old statement of mine is applicable in many contexts, including the current one:
"In short, just as the Multics mentality of careful access controls shows up throughout Unix, the cretinous CP/M mentality of uncontrolled havoc shows up in DOS and all its mutant children." --tchrist
I'll finish up by including an interesting article that turned up in a thread on comp.unix.programmer. There's a good bit of noise there, but also some interesting technical data as well.
I cannot speak for other BSDs, but in BSD/OS 4.0, the model (the code is not yet fully implemented) is that the sfork() call -- essentially the same as Plan 9's rfork() and Linux's clone() -- is the "one true" process creator. (Process 0, which forks init and does other similar work during bootstrapping, is never really "created": it exists in the
Putting aside the fundamental misunderstanding that "Ed@eds.net" apparently had when he started trol-- er, I mean began this discussion,
In addition:
Any thread can wipe itself out and run some other executable image instead (Unix "exec"). This wipes out any parts of memory not marked "preserve across exec"[%], partly just to match tradition, partly for ease of implementation, and partly for security when executing setuid binaries. (In other words, it does not *have* to be done this way. Given that current hardware tends to implement binaries that tend not to be entirely position-independent, we make concessions to efficiency here. We say: "We could not figure out how to make the old image hang around while the new image is loaded, and then give the old image a chance to remove itself if that is what it intended. So even though it looks like this action is made of a bunch of simpler atomic actions, we could not figure out a nice way to break it down.")
[% Some systems have no way to mark any such sections, in which case *all* memory "goes away" on exec. This is why exec takes argv and envp: to pass *some* data across the operation. "Leave memory region R" alone would suffice for the same purpose, and could be more efficient -- perhaps substantially so.]
Now, one can argue that "make a thread-copy and immediately exec", which is the pair of primitives that emulates other OS's "create new process running program P" operation, ought to be less efficient than simply having a "create new process running program P" operation (whether that is spelled spawn() or CreateProcess() or SYS$CREPRC or whatever -- let me use spawn() here for short). That argument makes some sense to me. Given a thread+exec model, fundamentally, spawn() is just "create thread, then exec". If there is any overhead in returning to user code, then having the user code immediately turn around and exec, all of that overhead can be eliminated.
But if you take a look at otherwise "reasonably comparable" systems that *do* offer "spawn" instead of fork+exec, something strange happens. The overhead for processes in those systems turns out to be *greater* than it is in the Unix-like systems. (Examples: VMS vs 4.1BSD on a VAX; NT vs Linux on an x86.) This overhead leads people to write "all in one" packages on the "spawn" systems (e.g., the directory lister is usually built into the user interface), while the relative lack of overhead in the fork+exec systems leads people to write smaller "tool" programs (the directory lister is usually a separate program, and hence works with pipes and "wc" word counters and "lpr" printer spooling and so on[%]). Perhaps the people who wrote the spawn() systems were just not as good as the people who wrote the fork+exec systems, but in any case, it seems odd.
Now for many side points, even if one of them was the main point of the original article. First, removing all the biasing wording:
There are two reasons for having a parent/child relationship in fork().
First, we need to distinguish between the original thread (process) and the new thread (process). We can arbitrarily label the original the "parent" and the new clone the "child". Or we could label them "old" and "new", or "Fred" and "Barney", or whatever, but "parent" and "child" works.
Second, any time any program runs any other program, it *might* care whether that other program succeeds. If there is *no* relationship between old and new, as suggested above, there is also no way for the creator to get information on the createe. So there must be *some* relationship: even if it is not a tree-structured parent/child thing, at the very least there is a "creator/createe" relationship, from the very fact that one process spawned the other. Using a parent/child relationship, and tying it to the return value from fork() (the thread/process id), is probably the simplest way of expressing this. Even when you are not doing cloning -- even when the only call you have is spawn() -- there is still a "creator" (spawner) and "createe" (spawnee), and those remain "parent" and "child", whether or not the OS tracks it.
"Natural" is one of those "marketing" type words that people use to sell one shampoo vs another (ours contains 2,4-di-poly-... so ours is More Natural!). But if you want to have a ProcessManager do the creating, you can code that yourself on any modern Unix system. Just write a program that listens for IPC requests to create new processes. Run it once, then send those IPC requests. The listening program is your ProcessManager and the IPC requests invoke it.
Problem solved. Next?
If you like the taste of ice cream more than that of vegetables, nothing anyone can say about the health qualities of either is going to change your mind about which tastes better.
In some systems, there are definite "right" vs "wrong" answers. "Everyone knows" that objects are naturally at rest -- if I roll a baseball on the ground, it always stops rolling eventually -- but in physics, Aristotle was wrong; Newton supplied a "righter" model. In this case, however, you have set up a system in which only you can possibly be right: "By `right' I mean something fits my intuition. A process manager fits my intuition, so any other model is wrong." There is nothing to prove or disprove here; you are letting your intuition dictate the answer, and your intuition is yours alone.
If so, you will have to come up with more objective criteria.
This is not a good mental model for Unix systems, and indeed, not a good mental model for many other non-Unix-like systems. To stick with traditional Unix systems (where fork() is "create new kernel thread, and immediately unshare all user memory"), a "process" is made up of:
- an identifier (Process ID or "pid");
- an address space (which might map to a
.exe, or might not;
the exec() call always creates such a mapping, but once exec'ed,
a process can generate and/or load new code and data [a la a "DLL"
in Microsoft-ese], and/or toss out its existing code and data,
as long it is careful);
- file descriptors (references to open files/pipes/IPC);
- credentials (~= privileges);
- resource limits;
- any other things I cannot think of off the top of my head.
Any process can change or rearrange any of these except its PID: the PID is the outside world's "true name" for the process. (The kernel might use a data pointer inside, if that seems more efficient and/or appropriate, but the outside-world name is the PID.)At the OS level, there is only fork() and exec(); system() is a C library (non-OS-level) thing. Clone() is just fork() spelled sideways, and the sideways spelling is just to work around the fact that, historically, fork() implies "copy (do not share) the resources", which tends to be slow. (Copy-on-write helps a lot, but not so much that people are not still drawn to some other mechanism, whether it is the limited vfork() or the flexible sfork()/rfork()/clone(), to avoid the copy altogether.) If you prefer, fork() is just clone() spelled sideways; as noted way at the top, the true primitive is "make a new thread with everything shared".
Now, once you have made the new, all-shared thread, you can do this in the "new" thread (as a shell might, to do "ls | wc"):
- 1 split off the file descriptors
- [new thread only, again]
The "split off the file descriptors" steps are required so that the new thread does not change or close the old thread's (shared) descriptors, which in step (2) would make the pipe available to the shell itself (the shell does not want it), and in step (3b) would remove "wc"'s access to the read side of the pipe (which would be disastrous).2 create a pipe
3 make another new, all-shared thread
3a split off the file descriptors
3b close the read side of the pipe
3c move the write side of the pipe to STDOUT_FILENO
3d exec "/bin/ls"
[NOTREACHED]
4 close the write side of the pipe
5 move the read side of the pipe to STDIN_FILENO
6 exec "/usr/bin/wc"
(Since rfork/clone take an argument, steps 1 and 3a are actually implicit, via "pid = xyzzyfork(SHARE_ALL_BUT_DESCRIPTORS)". That means the process above is actually 8 steps long -- 9 if you add in the initial fork.)
Note that a parent/child relationship occurs between "ls" and "wc" here, even though neither program wants it. This is not a *problem*, but it has no advantage either; it is just a side effect of the order of user-level manipulations involved in connecting the output of "ls" to the input of "wc". If the shell wants to be the parent of both ls and wc, the "make a pipe" step has to occur earlier and the sequences needs to be slightly different. (In fact, old versions of the Bourne shell used the above sequence, while modern shells *do* create the pipe earlier and remain the parent of each process in the pipeline.)
The "traditional spawn()" model looks like this:
2 move the current STDOUT_FILENO out of the way
3 move the write side of the pipe to STDOUT_FILENO
4 spawn "/bin/ls"
5 close the write side of the pipe
6 move the current STDIN_FILENO out of the way
7 move the read side of the pipe to STDIN_FILENO
8 spawn "/usr/bin/wc"
9 close the read side of the pipe
10 move the saved STDIN_FILENO back
11 move the saved STDOUT_FILENO back
In other words, it takes 11 steps, not 9, with a "spawn" model. Even though the fork and exec steps are combined (saving one step per fork+exec pair on the Unix shell side), the number of steps does not go down. The reason is that the spawner must do all the manipulation up front: there is no chance to change things around between the "create new process" step and the "take flying leap into new object file" step.
There is really very little to draw. Whoever calls fork() is a parent. The clone copy is a child.
My comments are distributed under the LGPL license. Moderating down my posts is a denying of the open source movement.
But sales figures, naturally, don't tell the whole story. Of equal (or more) importance would be net margins, and Microsoft maintains better margins than almost any other large company in existence. For example, GM had $161B in sales last year - pretty big, right? But auto manufacturing is a very low-margin business - they had just 1.8% net margins, or about $3B in profit. By contrast, Microsoft had 36% net margins last year, or over $5B in profit, well exceeding GM. They also (just) exceeded Wal-Mart's profits for last year, beating out another Dow component. That's 3 of the Dow 30... I haven't checked the other 27, but I'd bet MS turned more profit than most of those as well, and had just as comparable sales numbers.
Sure, Bill's money has to come from somewhere. Their profits are impressive -- but generated by monopoly sales in a booming market and therefore threatened by state intervention as well as future competition. This isn't the same as a margin of 1.8% in a mature competitive environment.
GM is already considered mismanaged as compared to Ford and Chrysler, and their margin may be expected to grow if they get their act together. MS's margin, OTOH, can only reasonably be expected to fall in the long run, for whichever of a whole variety of reasons (increasing development costs and market saturation come to mind besides what's mentioned above).
More impressive to me, by far, is that Microsoft currently has somewhere around $20 billion in cash reserves, depending on which day you look. In other words, they have over a year's worth of sales, in cash, on hand, with no debt whatsoever. I don't think they're going anywhere anytime soon. In fact, the cash alone accounts for 5-10% of their stock price, again depending on what day you look.
Fundamentally speaking, having 5-10% of the stock price backed by assets still leaves 90-95% uncovered. How many assets does Microsoft own besides their cash, anyway? They don't own manufacturing plants or oil platforms or warehouses full of tangible durable goods, just some buildings with a bunch of PCs and rapidly outdated software.
Seriously, though, stock prices aren't only driven by raw sales or profit numbers; far from it. They're driven by *growth* as well. Is Microsoft, as big as they are, growing faster than Wal-Mart? You damn skippy they are.
CaseyB: something just popped out of your ass. Where did you learn you trade you stupid fuck.
BSD contained the freely available reference implementation of IPv4. Chameleon and espescially Trumpet were the companies that actually shipped working IP suites for Windows, and who let the Windows-masses get on the net in the first place. There wouldn't have been a demand for Windows TCP/IP if Trumpet and Chameleon hadn't created it. Microsoft was set up to use MSN to duke it out with AOL and Compuserve for dialins into proprietary networks, not to deal with the internet. Until, of course, all their users suddenly said "Hey, we like the open Internet." And then it still took them a year or so to notice.
The BSD TCP/IP code, or code based on it, is present on every single Windows and most every Unix Internet-attached computer in the world. That's a pretty big "install base," and easily musters most current internet users. Chameleon and Trumpet had 99% of the Windows TCP/IP install base until Windows 95, and still have all of the Windows TCP/IP install base for everyone who has not yet upgraded past Windows 3.11 and a substantial amount of the people still running earlier versions of Windows 95 who kept using them instead of Microsoft's implementation.
Mythical man month is a very good book. It was written by a key figure in IBM's development of IBM's S/360 OS. He gives very good advice on planning and developing data processing systems.
His basic premise is that a man and month are NOT interchangeable. That is, a project requiring 1 person working 6 months can NOT be converted to 6 people working 1 month.
Frederick P. Brooks, Jr.
the mythical man-month
Essays on Software Engineering
Addison-Wesley ISBN 0-201-00650-2
If you can't find a copy of the lecture specifically, I am sure that Dr. Brooks covers all the same grounds in the 20th anniversary edition of "The Mythical Man-Month" pub Addison-Wesley ISBM0-201-83595-9.
I think one of the reasons people become so enthralled with the economic/political philosophy of Linux (as opposed to the people who use Linux, because, hey, free UNIX) is because it does something extremely rare (I would say unprecedented) politically.